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

📄 call.c

📁 第二层隧道模块l2tp源码,开发环境为linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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. * * Handle a call as a separate thread */#include <stdio.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/wait.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include <termios.h>#include "l2tp.h"#ifdef USE_KERNEL#include <sys/ioctl.h>#endifstruct buffer *new_payload (struct sockaddr_in peer){    struct buffer *tmp = new_buf (MAX_RECV_SIZE);    if (!tmp)        return NULL;    tmp->peer = peer;    tmp->start += sizeof (struct payload_hdr);    tmp->len = 0;    return tmp;}inline void recycle_payload (struct buffer *buf, struct sockaddr_in peer){    buf->start = buf->rstart + sizeof (struct payload_hdr);    buf->len = 0;    buf->peer = peer;}void add_payload_hdr (struct tunnel *t, struct call *c, struct buffer *buf){    struct payload_hdr *p;    buf->start -= sizeof (struct payload_hdr);    buf->len += sizeof (struct payload_hdr);    /* Account for no offset */    buf->start += 4;    buf->len -= 4;    if (!c->fbit && !c->ourfbit)    {        /* Forget about Ns and Nr fields then */        buf->start += 4;        buf->len -= 4;    }    if (!c->lbit)    {        /* Forget about specifying the length */        buf->start += 2;        buf->len -= 2;    }    p = (struct payload_hdr *) buf->start;/*	p->ver = htons(c->lbit | c->rbit | c->fbit | c->ourfbit | VER_L2TP); */    p->ver = htons (c->lbit | c->fbit | c->ourfbit | VER_L2TP);    if (c->lbit)    {        p->length = htons ((_u16) buf->len);    }    else    {        p = (struct payload_hdr *) (((char *) p) - 2);    }    p->tid = htons (t->tid);    p->cid = htons (c->cid);    if (c->fbit || c->ourfbit)    {        p->Ns = htons (c->data_seq_num);        p->Nr = htons (c->data_rec_seq_num);    }    c->data_seq_num++;/*	c->rbit=0; */}int read_packet (struct buffer *buf, int fd, int convert){    unsigned char c;    unsigned char escape = 0;    unsigned char *p;    static unsigned char rbuf[MAX_RECV_SIZE];    static int pos = 0;    static int max = 0;    int res;    int errors = 0;    /* Read a packet, doing async->sync conversion if necessary */    p = buf->start;    while (1)    {        if (pos >= max)        {            max = read (fd, rbuf, sizeof (rbuf));            res = max;            pos = 0;        }        else        {            res = 1;        }        c = rbuf[pos++];        if (res < 1)        {            if (res == 0)            {                /*                   * Hmm..  Nothing to read.  It happens                 */                return 0;/*			} else if ((errno == EINTR ) || (errno == EAGAIN)) { */            }            else if ((errno == EIO) || (errno == EINTR) || (errno == EAGAIN))            {                /*                   * Oops, we were interrupted!                   * Or, we ran out of data too soon                   * anyway, we discared whatever it is we                   * have                 */                return 0;            }            errors++;            log (LOG_DEBUG, "%s: Error %d (%s)\n", __FUNCTION__, errno,                 strerror (errno));            if (errors > 10)            {                log (LOG_DEBUG,                     "%s: Too many errors.  Declaring call dead.\n",                     __FUNCTION__);                return -errno;            }            continue;        }        switch (c)        {        case PPP_FLAG:            if (escape)            {                log (LOG_DEBUG, "%s: got an escaped PPP_FLAG\n",                     __FUNCTION__);                return -EINVAL;            }            if (convert)            {                if (!buf->len)                    break;                /* Drop the FCS */                buf->len -= 2;            }            else            {                if (buf->len < buf->maxlen)                {                    *p = c;                    p++;                    buf->len++;                }            }            return buf->len;        case PPP_ESCAPE:            escape = PPP_TRANS;            if (convert)                break;        default:            if (convert)                c ^= escape;            escape = 0;            if (buf->len < buf->maxlen)            {                *p = c;                p++;                buf->len++;                break;            };            log (LOG_WARN, "%s: read overrun\n", __FUNCTION__);            return -EINVAL;        }    }    /* I should never get here */    log (LOG_WARN, "%s: You should not see this message.  If you do, please		       enter a bug report at http://sourceforge.net/projects/l2tpd", __FUNCTION__);    return -EINVAL;}void call_close (struct call *c){    struct buffer *buf;    struct schedule_entry *se, *ose;    struct call *tmp, *tmp2;    if (!c || !c->container)    {        log (LOG_DEBUG, "%s: called on null call or containerless call\n",             __FUNCTION__);        return;    }    if (c == c->container->self)    {        /*         * We're actually closing the         * entire tunnel         */        /* First deschedule any remaining packet transmissions           for this tunnel.  That means Hello's and any reminaing           packets scheduled for transmission.  This is a very           nasty little piece of code here. */        se = events;        ose = NULL;        while (se)        {            if ((((struct buffer *) se->data)->tunnel == c->container)                || ((struct tunnel *) se->data == c->container))            {#ifdef DEBUG_CLOSE                log (LOG_DEBUG, "%s: Descheduling event\n", __FUNCTION__);#endif                if (ose)                {                    ose->next = se->next;                    if ((struct tunnel *) se->data != c->container)                        toss ((struct buffer *) (se->data));                    free (se);                    se = ose->next;                }                else                {                    events = se->next;                    if ((struct tunnel *) se->data != c->container)                        toss ((struct buffer *) (se->data));                    free (se);                    se = events;                }            }            else            {                ose = se;                se = se->next;            }        }        if (c->closing)        {            /* Really close this tunnel, as our               StopCCN has been ack'd */#ifdef DEBUG_CLOSE            log (LOG_DEBUG, "%s: Actually closing tunnel %d\n", __FUNCTION__,                 c->container->ourtid);#endif#ifdef USE_KERNEL            if (kernel_support)                ioctl (server_socket, L2TPIOCDELTUNNEL, c->container->ourtid);#endif            destroy_tunnel (c->container);            return;        }        /*           * We need to close, but need to provide reliable delivery           * of the final StopCCN. We record our state to know when           * we have actually received an ACK on our StopCCN         */        c->closeSs = c->container->control_seq_num;        buf = new_outgoing (c->container);        add_message_type_avp (buf, StopCCN);        if (c->container->hbit)        {            mk_challenge (c->container->chal_them.vector, VECTOR_SIZE);            add_randvect_avp (buf, c->container->chal_them.vector,                              VECTOR_SIZE);        }        add_tunnelid_avp (buf, c->container->ourtid);        if (c->result < 0)            c->result = RESULT_CLEAR;        if (c->error < 0)            c->error = 0;        add_result_code_avp (buf, c->result, c->error, c->errormsg,                             strlen (c->errormsg));        add_control_hdr (c->container, c, buf);        if (packet_dump)            do_packet_dump (buf);#ifdef DEBUG_CLOSE        log (LOG_DEBUG, "%s: enqueing close message for tunnel\n",             __FUNCTION__);#endif        control_xmit (buf);        /*           * We also need to stop all traffic on any calls contained           * within us.         */        tmp = c->container->call_head;        while (tmp)        {            tmp2 = tmp->next;            tmp->needclose = 0;            tmp->closing = -1;            call_close (tmp);            tmp = tmp2;        }        log (LOG_LOG,             "%s : Connection %d closed to %s, port %d (%s)\n", __FUNCTION__,             c->container->tid,             IPADDY (c->container->peer.sin_addr),             ntohs (c->container->peer.sin_port), c->errormsg);    }    else    {        /*           * Just close a call         */#ifdef USE_KERNEL        struct l2tp_call_opts co;#endif        if (c->zlb_xmit)            deschedule (c->zlb_xmit);/*		if (c->dethrottle) deschedule(c->dethrottle); */        if (c->closing)        {#ifdef DEBUG_CLOSE            log (LOG_DEBUG, "%s: Actually closing call %d\n", __FUNCTION__,                 c->ourcid);#endif

⌨️ 快捷键说明

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