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

📄 avp.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. * * Attribute Value Pair handler routines */#include <stdlib.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <netinet/in.h>#include "l2tp.h"#define AVP_MAX 39struct avp avps[] = {    {0, 1, &message_type_avp, "Message Type"},    {1, 1, &result_code_avp, "Result Code"},    {2, 1, &protocol_version_avp, "Protocol Version"},    {3, 1, &framing_caps_avp, "Framing Capabilities"},    {4, 1, &bearer_caps_avp, "Bearer Capabilities"},    {5, 0, NULL, "Tie Breaker"},    {6, 0, &firmware_rev_avp, "Firmware Revision"},    {7, 0, &hostname_avp, "Host Name"},    {8, 1, &vendor_avp, "Vendor Name"},    {9, 1, &assigned_tunnel_avp, "Assigned Tunnel ID"},    {10, 1, &receive_window_size_avp, "Receive Window Size"},    {11, 1, &challenge_avp, "Challenge"},    {12, 0, NULL, "Q.931 Cause Code"},    {13, 1, &chalresp_avp, "Challenge Response"},    {14, 1, &assigned_call_avp, "Assigned Call ID"},    {15, 1, &call_serno_avp, "Call Serial Number"},    {16, 1, NULL, "Minimum BPS"},    {17, 1, NULL, "Maximum BPS"},    {18, 1, &bearer_type_avp, "Bearer Type"},    {19, 1, &frame_type_avp, "Framing Type"},    {20, 1, &packet_delay_avp, "Packet Processing Delay"},    {21, 1, &dialed_number_avp, "Dialed Number"},    {22, 1, &dialing_number_avp, "Dialing Number"},    {23, 1, &sub_address_avp, "Sub-Address"},    {24, 1, &tx_speed_avp, "Transmit Connect Speed"},    {25, 1, &call_physchan_avp, "Physical channel ID"},    {26, 0, NULL, "Initial Received LCP Confreq"},    {27, 0, NULL, "Last Sent LCP Confreq"},    {28, 0, NULL, "Last Received LCP Confreq"},    {29, 1, &ignore_avp, "Proxy Authen Type"},    {30, 0, &ignore_avp, "Proxy Authen Name"},    {31, 0, &ignore_avp, "Proxy Authen Challenge"},    {32, 0, &ignore_avp, "Proxy Authen ID"},    {33, 1, &ignore_avp, "Proxy Authen Response"},    {34, 1, NULL, "Call Errors"},    {35, 1, &ignore_avp, "ACCM"},    {36, 1, &rand_vector_avp, "Random Vector"},    {37, 1, NULL, "Private Group ID"},    {38, 0, &rx_speed_avp, "Receive Connect Speed"},    {39, 1, &seq_reqd_avp, "Sequencing Required"}};char *msgtypes[] = {    NULL,    "Start-Control-Connection-Request",    "Start-Control-Connection-Reply",    "Start-Control-Connection-Connected",    "Stop-Control-Connection-Notification",    NULL,    "Hello",    "Outgoing-Call-Request",    "Outgoing-Call-Reply",    "Outgoing-Call-Connected",    "Incoming-Call-Request",    "Incoming-Call-Reply",    "Incoming-Call-Connected",    NULL,    "Call-Disconnect-Notify",    "WAN-Error-Notify",    "Set-Link-Info"};char *stopccn_result_codes[] = {    "Reserved",    "General request to clear control connection",    "General error--Error Code indicates the problem",    "Control channel already exists",    "Requester is not authorized to establish a control channel",    "The protocol version of the requester is not supported--Error Code indicates the highest version supported",    "Requester is being shut down",    "Finite State Machine error"};char *cdn_result_codes[] = {    "Reserved",    "Call disconnected due to loss of carrier",    "Call disconnected for the reason indicated in error code",    "Call disconnected for administrative reasons",    "Call failed due to lack of appropriate facilities being available (temporary condition)",    "Call failed due to lack of appropriate facilities being available (permanent condition)",    "Invalid destination",    "Call failed due to no carrier detected",    "Call failed due to lack of a dial tone",    "Call was no established within time allotted by LAC",    "Call was connected but no appropriate framing was detect"};void wrong_length (struct call *c, char *field, int expected, int found,                   int min){    if (min)        snprintf (c->errormsg, sizeof (c->errormsg),                  "%s: expected at least %d, got %d", field, expected, found);    else        snprintf (c->errormsg, sizeof (c->errormsg),                  "%s: expected %d, got %d", field, expected, found);    c->error = ERROR_LENGTH;    c->result = RESULT_ERROR;    c->needclose = -1;}/* * t, c, data, and datalen may be assumed to be defined for all avp's */int message_type_avp (struct tunnel *t, struct call *c, void *data,                      int datalen){    /*     * This will be with every control message.  It is critical that this     * procedure check for the validity of sending this kind of a message     * (assuming sanity check)     */    _u16 *raw = data;    c->msgtype = ntohs (raw[3]);    if (datalen != 8)    {        if (DEBUG)            log (LOG_DEBUG, "%s: wrong size (%d != 8)\n", __FUNCTION__,                 datalen);        wrong_length (c, "Message Type", 8, datalen, 0);        return -EINVAL;    }    if ((c->msgtype > MAX_MSG) || (!msgtypes[c->msgtype]))    {        if (DEBUG)            log (LOG_DEBUG, "%s: unknown message type %d\n", __FUNCTION__,                 c->msgtype);        return -EINVAL;    }    if (debug_avp)        if (DEBUG)            log (LOG_DEBUG, "%s: message type %d (%s)\n", __FUNCTION__,                 c->msgtype, msgtypes[c->msgtype]);#ifdef SANITY    if (t->sanity)    {        /*         * Look ou our state for each message and make sure everything         * make sense...         */        if ((c != t->self) && (c->msgtype < Hello))        {            if (DEBUG)                log (LOG_DEBUG,                     "%s: attempting to negotiate tunnel inside a call!\n",                     __FUNCTION__);            return -EINVAL;        }        switch (c->msgtype)        {        case SCCRQ:            if ((t->state != 0) && (t->state != SCCRQ))            {                /*                 * When we handle tie breaker AVP's, then we'll check                 * to see if we've both requested tunnels                 */                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate SCCRQ with state != 0\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case SCCRP:            if (t->state != SCCRQ)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate SCCRP with state != SCCRQ!\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case SCCCN:            if (t->state != SCCRP)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate SCCCN with state != SCCRP!\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case ICRQ:            if (t->state != SCCCN)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate ICRQ when state != SCCCN\n",                         __FUNCTION__);                return -EINVAL;            }            if (c != t->self)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate ICRQ on a call!\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case ICRP:            if (t->state != SCCCN)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate ICRP on tunnel!=SCCCN\n",                         __FUNCTION__);                return -EINVAL;            }            if (c->state != ICRQ)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate ICRP when state != ICRQ\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case ICCN:            if (c->state != ICRP)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate ICCN when state != ICRP\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case SLI:            if (c->state != ICCN)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate SLI when state != ICCN\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case OCRP:             /* jz: case for ORCP */            if (t->state != SCCCN)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate OCRP on tunnel!=SCCCN\n",                         __FUNCTION__);                return -EINVAL;            }            if (c->state != OCRQ)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate OCRP when state != OCRQ\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case OCCN:             /* jz: case for OCCN */            if (c->state != OCRQ)            {                if (DEBUG)                    log (LOG_DEBUG,                         "%s: attempting to negotiate OCCN when state != OCRQ\n",                         __FUNCTION__);                return -EINVAL;            }            break;        case StopCCN:        case CDN:        case Hello:            break;        default:            log (LOG_WARN, "%s: i don't know how to handle %s messages\n",                 __FUNCTION__, msgtypes[c->msgtype]);            return -EINVAL;        }    }#endif    if (c->msgtype == ICRQ)    {        struct call *tmp;        if (debug_avp)        {            if (DEBUG)                log (LOG_DEBUG, "%s: new incoming call\n", __FUNCTION__);        }        tmp = new_call (t);        if (!tmp)        {            log (LOG_WARN, "%s: unable to create new call\n", __FUNCTION__);            return -EINVAL;        }        tmp->next = t->call_head;        t->call_head = tmp;        t->count++;        /*           * Is this still safe to assume that the head will always           * be the most recent call being negotiated?           * Probably...  FIXME anyway...         */    }    return 0;}int rand_vector_avp (struct tunnel *t, struct call *c, void *data,                     int datalen){    int size;    _u16 *raw = (_u16 *) data;    size = (raw[0] & 0x0FFF) - 6;    if (t->sanity)    {        if (size < 0)        {            if (DEBUG)                log (LOG_DEBUG, "%s: Random vector too small (%d < 0)\n",                     __FUNCTION__, size);            wrong_length (c, "Random Vector", 6, datalen, 1);            return -EINVAL;        }        if (size > MAX_VECTOR_SIZE)        {            if (DEBUG)                log (LOG_DEBUG, "%s: Random vector too large (%d > %d)\n",                     __FUNCTION__, datalen, MAX_VECTOR_SIZE);            wrong_length (c, "Random Vector", 6, datalen, 1);            return -EINVAL;        }    }    if (debug_avp)        log (LOG_DEBUG, "%s: Random Vector of %d octets\n", __FUNCTION__,             size);    t->chal_us.vector = (unsigned char *) &raw[3];    t->chal_us.vector_len = size;    return 0;}int ignore_avp (struct tunnel *t, struct call *c, void *data, int datalen){    /*     * The spec says we have to accept authentication information     * even if we just ignore it, so that's exactly what     * we're going to do at this point.  Proxy authentication is such     * a rediculous security threat anyway except from local     * controled machines.     *     * FIXME: I need to handle proxy authentication as an option.     * One option is to simply change the options we pass to pppd.     *     */    if (debug_avp)    {        if (DEBUG)            log (LOG_DEBUG, "%s : Ignoring AVP\n", __FUNCTION__);    }    return 0;}int seq_reqd_avp (struct tunnel *t, struct call *c, void *data, int datalen){#ifdef SANITY    if (t->sanity)    {        if (datalen != 6)        {            if (DEBUG)                log (LOG_DEBUG,                     "%s: avp is incorrect size.  %d != 6\n", __FUNCTION__,                     datalen);            wrong_length (c, "Sequencing Required", 6, datalen, 1);            return -EINVAL;        }        switch (c->msgtype)        {        case ICCN:            break;        default:            if (DEBUG)                log (LOG_DEBUG,                     "%s: sequencing required not appropriate for %s!\n",                     __FUNCTION__, msgtypes[c->msgtype]);            return -EINVAL;        }    }#endif    if (debug_avp)    {        if (DEBUG)            log (LOG_DEBUG, "%s: peer requires sequencing.\n", __FUNCTION__);    }    c->seq_reqd = -1;    return 0;}int result_code_avp (struct tunnel *t, struct call *c, void *data,                     int datalen){    /*     * Find out what version of l2tp the other side is using.     * I'm not sure what we're supposed to do with this but whatever..     */    int error;    int result;    _u16 *raw = data;#ifdef SANITY    if (t->sanity)    {        if (datalen < 10)

⌨️ 快捷键说明

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