Annotation of embedaddon/libpdel/ppp/ppp_lcp.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (c) 2001-2002 Packet Design, LLC.
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Subject to the following obligations and disclaimer of warranty,
        !             7:  * use and redistribution of this software, in source or object code
        !             8:  * forms, with or without modifications are expressly permitted by
        !             9:  * Packet Design; provided, however, that:
        !            10:  * 
        !            11:  *    (i)  Any and all reproductions of the source or object code
        !            12:  *         must include the copyright notice above and the following
        !            13:  *         disclaimer of warranties; and
        !            14:  *    (ii) No rights are granted, in any manner or form, to use
        !            15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            16:  *         on advertising, endorsements, or otherwise except as such
        !            17:  *         appears in the above copyright notice or in the software.
        !            18:  * 
        !            19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            36:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            37:  *
        !            38:  * Author: Archie Cobbs <archie@freebsd.org>
        !            39:  */
        !            40: 
        !            41: #include "ppp/ppp_defs.h"
        !            42: #include "ppp/ppp_fsm_option.h"
        !            43: #include "ppp/ppp_fsm.h"
        !            44: #include "ppp/ppp_auth.h"
        !            45: #include "ppp/ppp_lcp.h"
        !            46: #include "ppp/ppp_util.h"
        !            47: 
        !            48: /* Memory type */
        !            49: #define LCP_MTYPE              "lcp"
        !            50: 
        !            51: /* LCP configuration options */
        !            52: enum lcp_option {
        !            53:        LCP_OPT_VENDOR          =0,     /* Vendor specific */
        !            54:        LCP_OPT_MRU             =1,     /* Maximum-Receive-Unit */
        !            55:        LCP_OPT_ACCMAP          =2,     /* Async-Control-Character-Map */
        !            56:        LCP_OPT_AUTH            =3,     /* Authentication-Protocol */
        !            57:        LCP_OPT_QUAL            =4,     /* Quality-Protocol */
        !            58:        LCP_OPT_MAGIC           =5,     /* Magic-Number */
        !            59:        LCP_OPT_PFCMP           =7,     /* Protocol-Field-Compression */
        !            60:        LCP_OPT_ACFCMP          =8,     /* Address&Ctrl-Field-Compression */
        !            61:        LCP_OPT_FCSALT          =9,     /* FCS-Alternatives */
        !            62:        LCP_OPT_SDP             =10,    /* Self-Dscribing-Padding */
        !            63:        LCP_OPT_NBMODE          =11,    /* Numbered-Mode */
        !            64:        LCP_OPT_MULTILINK       =12,    /* Multi-link procedure (?) */
        !            65:        LCP_OPT_CALLBK          =13,    /* Callback */
        !            66:        LCP_OPT_CTTIME          =14,    /* Connect time */
        !            67:        LCP_OPT_COMPFR          =15,    /* Compound-Frames */
        !            68:        LCP_OPT_NDS             =16,    /* Nominal-Data-Encapsulation */
        !            69:        LCP_OPT_MRRU            =17,    /* Multi-link MRRU size */
        !            70:        LCP_OPT_SHSEQ           =18,    /* Short seq number header */
        !            71:        LCP_OPT_EDISC           =19,    /* Unique endpoint discrimiator */
        !            72:        LCP_OPT_PROPR           =20,    /* Proprietary */
        !            73:        LCP_OPT_DCEID           =21     /* DCE-Identifier */
        !            74: };
        !            75: 
        !            76: /* Supported and required FSM codes for normal LCP */
        !            77: #define LCP_SUPPORTED_CODES            \
        !            78:          (1 << FSM_CODE_CONFIGREQ)     \
        !            79:        | (1 << FSM_CODE_CONFIGACK)     \
        !            80:        | (1 << FSM_CODE_CONFIGNAK)     \
        !            81:        | (1 << FSM_CODE_CONFIGREJ)     \
        !            82:        | (1 << FSM_CODE_TERMREQ)       \
        !            83:        | (1 << FSM_CODE_TERMACK)       \
        !            84:        | (1 << FSM_CODE_CODEREJ)       \
        !            85:        | (1 << FSM_CODE_PROTOREJ)      \
        !            86:        | (1 << FSM_CODE_ECHOREQ)       \
        !            87:        | (1 << FSM_CODE_ECHOREP)       \
        !            88:        | (1 << FSM_CODE_DISCREQ)       \
        !            89:        | (1 << FSM_CODE_IDENT)         \
        !            90:        | (1 << FSM_CODE_TIMEREM)
        !            91: #define LCP_REQUIRED_CODES             \
        !            92:          (1 << FSM_CODE_CONFIGREQ)     \
        !            93:        | (1 << FSM_CODE_CONFIGACK)     \
        !            94:        | (1 << FSM_CODE_CONFIGNAK)     \
        !            95:        | (1 << FSM_CODE_CONFIGREJ)     \
        !            96:        | (1 << FSM_CODE_TERMREQ)       \
        !            97:        | (1 << FSM_CODE_TERMACK)       \
        !            98:        | (1 << FSM_CODE_CODEREJ)       \
        !            99:        | (1 << FSM_CODE_PROTOREJ)      \
        !           100:        | (1 << FSM_CODE_ECHOREQ)       \
        !           101:        | (1 << FSM_CODE_ECHOREP)
        !           102: 
        !           103: /* Supported and required FSM codes for LCP sent over a multilink bundle */
        !           104: #define MP_LCP_SUPPORTED_CODES         \
        !           105:          (1 << FSM_CODE_CODEREJ)       \
        !           106:        | (1 << FSM_CODE_PROTOREJ)      \
        !           107:        | (1 << FSM_CODE_ECHOREQ)       \
        !           108:        | (1 << FSM_CODE_ECHOREP)       \
        !           109:        | (1 << FSM_CODE_DISCREQ)       \
        !           110:        | (1 << FSM_CODE_IDENT)         \
        !           111:        | (1 << FSM_CODE_TIMEREM)
        !           112: #define MP_LCP_REQUIRED_CODES          \
        !           113:          (1 << FSM_CODE_CODEREJ)       \
        !           114:        | (1 << FSM_CODE_PROTOREJ)      \
        !           115:        | (1 << FSM_CODE_ECHOREQ)       \
        !           116:        | (1 << FSM_CODE_ECHOREP)
        !           117: 
        !           118: struct eid_type {
        !           119:        u_char          min;
        !           120:        u_char          max;
        !           121:        const char      *desc;
        !           122: };
        !           123: 
        !           124: static const   struct eid_type eid_types[PPP_EID_CLASS_MAX] = {
        !           125:        { 0,    0,              "Null"  },      /* PPP_EID_CLASS_NULL */
        !           126:        { 1,    PPP_EID_MAXLEN, "Local" },      /* PPP_EID_CLASS_LOCAL */
        !           127:        { 4,    4,              "IP"    },      /* PPP_EID_CLASS_IP */
        !           128:        { 6,    6,              "MAC"   },      /* PPP_EID_CLASS_MAC */
        !           129:        { 4,    PPP_EID_MAXLEN, "Magic" },      /* PPP_EID_CLASS_MAGIC */
        !           130:        { 1,    PPP_EID_MAXLEN, "E.164" },      /* PPP_EID_CLASS_E164 */
        !           131: };
        !           132: 
        !           133: static opt_pr_t        lcp_pr_eid;
        !           134: 
        !           135: /* FSM options descriptors */
        !           136: const struct   ppp_fsm_optdesc lcp_opt_desc[] = {
        !           137:        { "Vendor",     LCP_OPT_VENDOR, 4, 255, 0,      NULL },
        !           138:        { "MRU",        LCP_OPT_MRU,    2, 2,   1,      ppp_fsm_pr_int16 },
        !           139:        { "ACCM",       LCP_OPT_ACCMAP, 4, 4,   1,      ppp_fsm_pr_hex32 },
        !           140:        { "Auth",       LCP_OPT_AUTH,   2, 255, 1,      ppp_auth_print},
        !           141:        { "Qual",       LCP_OPT_QUAL,   0, 255, 0,      NULL },
        !           142:        { "Magic",      LCP_OPT_MAGIC,  4, 4,   1,      ppp_fsm_pr_hex32 },
        !           143:        { "PFComp",     LCP_OPT_PFCMP,  0, 0,   1,      NULL },
        !           144:        { "ACFComp",    LCP_OPT_ACFCMP, 0, 0,   1,      NULL },
        !           145:        { "FCSAlt",     LCP_OPT_FCSALT, 1, 1,   0,      NULL },
        !           146:        { "SDP",        LCP_OPT_SDP,    1, 1,   0,      NULL },
        !           147:        { "NumMode",    LCP_OPT_NBMODE, 0, 255, 0,      NULL },
        !           148:        { "Callback",   LCP_OPT_CALLBK, 1, 255, 0,      NULL },
        !           149:        { "CnctTime",   LCP_OPT_CTTIME, 0, 255, 0,      NULL },
        !           150:        { "CompFrames", LCP_OPT_COMPFR, 0, 255, 0,      NULL },
        !           151:        { "NDEncap",    LCP_OPT_NDS,    0, 255, 0,      NULL },
        !           152:        { "MP-MRRU",    LCP_OPT_MRRU,   2, 2,   1,      ppp_fsm_pr_int16 },
        !           153:        { "MP-ShortSq", LCP_OPT_SHSEQ,  0, 0,   1,      NULL },
        !           154:        { "EID",        LCP_OPT_EDISC,  1,
        !           155:                                1 + PPP_EID_MAXLEN, 1,  lcp_pr_eid },
        !           156:        { "Proprietry", LCP_OPT_PROPR,  0, 255, 0,      NULL },
        !           157:        { "DCE-Ident",  LCP_OPT_DCEID,  0, 255, 0,      NULL },
        !           158:        { NULL,         0,              0, 0,   0,      NULL }
        !           159: };
        !           160: 
        !           161: /* Default configuration options */
        !           162: static /*const*/ u_char lcp_default_mru[2] = {
        !           163:        (LCP_DEFAULT_MRU >> 8), (LCP_DEFAULT_MRU & 0xff)
        !           164: };
        !           165: static /*const*/ u_char lcp_default_accm[4] = {
        !           166:        0xff, 0xff, 0xff, 0xff
        !           167: };
        !           168: static /*const*/ u_char lcp_default_eid[1] = {
        !           169:        PPP_EID_CLASS_NULL
        !           170: };
        !           171: 
        !           172: /* Default configuration option list */
        !           173: static /*const*/ struct ppp_fsm_option lcp_opt_default_list[] = {
        !           174:        { LCP_OPT_MRU,          sizeof(lcp_default_mru), lcp_default_mru },
        !           175:        { LCP_OPT_ACCMAP,       sizeof(lcp_default_accm), lcp_default_accm },
        !           176:        { LCP_OPT_EDISC,        sizeof(lcp_default_eid), lcp_default_eid },
        !           177: };
        !           178: static const   struct ppp_fsm_options lcp_opt_default = {
        !           179:        sizeof(lcp_opt_default_list) / sizeof(*lcp_opt_default_list),
        !           180:        lcp_opt_default_list
        !           181: };
        !           182: 
        !           183: /* FSM type for LCP */
        !           184: static ppp_fsm_type_destroy_t          ppp_lcp_destroy;
        !           185: static ppp_fsm_type_build_conf_req_t   ppp_lcp_build_conf_req;
        !           186: static ppp_fsm_type_recv_conf_req_t    ppp_lcp_recv_conf_req;
        !           187: static ppp_fsm_type_recv_conf_rej_t    ppp_lcp_recv_conf_rej;
        !           188: static ppp_fsm_type_recv_conf_nak_t    ppp_lcp_recv_conf_nak;
        !           189: static ppp_fsm_type_get_magic_t                ppp_lcp_get_magic;
        !           190: 
        !           191: const struct   ppp_fsm_type ppp_fsm_lcp = {
        !           192:        "LCP",
        !           193:        PPP_PROTO_LCP,
        !           194:        LCP_SUPPORTED_CODES,
        !           195:        LCP_REQUIRED_CODES,
        !           196:        lcp_opt_desc,
        !           197:        &lcp_opt_default,
        !           198:        ppp_lcp_destroy,
        !           199:        ppp_lcp_build_conf_req,
        !           200:        ppp_lcp_recv_conf_req,
        !           201:        ppp_lcp_recv_conf_rej,
        !           202:        ppp_lcp_recv_conf_nak,
        !           203:        ppp_lcp_get_magic,
        !           204:        NULL,
        !           205:        NULL,
        !           206:        NULL
        !           207: };
        !           208: 
        !           209: const struct   ppp_fsm_type ppp_fsm_mp_lcp = {
        !           210:        "LCP",
        !           211:        PPP_PROTO_LCP,
        !           212:        MP_LCP_SUPPORTED_CODES,
        !           213:        MP_LCP_REQUIRED_CODES,
        !           214:        NULL,
        !           215:        NULL,
        !           216:        ppp_lcp_destroy,
        !           217:        NULL,
        !           218:        NULL,
        !           219:        NULL,
        !           220:        NULL,
        !           221:        NULL,
        !           222:        NULL,
        !           223:        NULL,
        !           224:        NULL
        !           225: };
        !           226: 
        !           227: /* LCP instance state */
        !           228: struct lcp {
        !           229:        struct ppp_lcp_config   conf;           /* initial config */
        !           230:        struct ppp_lcp_req      req;            /* current request state */
        !           231: };
        !           232: 
        !           233: /***********************************************************************
        !           234:                        PUBLIC FUNCTIONS
        !           235: ***********************************************************************/
        !           236: 
        !           237: struct ppp_fsm_instance *
        !           238: ppp_lcp_create(struct ppp_lcp_config *conf)
        !           239: {
        !           240:        struct ppp_fsm_instance *inst;
        !           241:        struct ppp_lcp_req *req;
        !           242:        struct lcp *lcp = NULL;
        !           243:        int nauth[2];
        !           244:        int i;
        !           245: 
        !           246:        /* Construct instance object */
        !           247:        if ((inst = MALLOC(LCP_MTYPE, sizeof(*inst))) == NULL)
        !           248:                return (NULL);
        !           249:        memset(inst, 0, sizeof(*inst));
        !           250:        inst->type = (conf != NULL) ? &ppp_fsm_lcp : &ppp_fsm_mp_lcp;
        !           251: 
        !           252:        /* Attach private data */
        !           253:        if ((lcp = MALLOC(LCP_MTYPE, sizeof(*lcp))) == NULL)
        !           254:                goto fail;
        !           255:        memset(lcp, 0, sizeof(*lcp));
        !           256:        inst->arg = lcp;
        !           257: 
        !           258:        /* No configuration required for MP LCP's */
        !           259:        if (conf == NULL)
        !           260:                goto no_conf;
        !           261: 
        !           262:        /* Sanity check and normalize configuration */
        !           263:        lcp->conf = *conf;
        !           264:        conf = &lcp->conf;
        !           265:        for (i = 0; i < 2; i++) {
        !           266:                if (conf->max_mru[i] == 0)
        !           267:                        conf->max_mru[i] = LCP_MAX_MRU;
        !           268:                if (conf->max_mrru[i] == 0)
        !           269:                        conf->max_mrru[i] = LCP_MAX_MRRU;
        !           270:                conf->min_mru[i] = MAX(conf->min_mru[i], LCP_MIN_MRU);
        !           271:                conf->max_mru[i] = MIN(conf->max_mru[i], LCP_MAX_MRU);
        !           272:                conf->min_mrru[i] = MAX(conf->min_mrru[i], LCP_MIN_MRRU);
        !           273:                conf->max_mrru[i] = MIN(conf->max_mrru[i], LCP_MAX_MRRU);
        !           274:        }
        !           275: 
        !           276:        /* Multilink cannot be both enabled and denied */
        !           277:        if (!conf->multilink[PPP_PEER]) {
        !           278:                conf->shortseq[PPP_SELF] = 0;
        !           279:                conf->shortseq[PPP_PEER] = 0;
        !           280:                if (conf->multilink[PPP_SELF]) {
        !           281:                        errno = EINVAL;
        !           282:                        goto fail;
        !           283:                }
        !           284:        }
        !           285: 
        !           286:        /* Check MRU values are self-consistent */
        !           287:        if (conf->min_mru[PPP_SELF] > conf->max_mru[PPP_SELF]
        !           288:            || conf->min_mru[PPP_PEER] > conf->max_mru[PPP_PEER]
        !           289:            || conf->min_mrru[PPP_SELF] > conf->max_mrru[PPP_SELF]
        !           290:            || conf->min_mrru[PPP_PEER] > conf->max_mrru[PPP_PEER]) {
        !           291:                errno = EINVAL;
        !           292:                goto fail;
        !           293:        }
        !           294: 
        !           295:        /* Check MRRU values are self-consistent (if multilink is possible) */
        !           296:        if (conf->multilink[PPP_PEER]
        !           297:            && (conf->min_mrru[PPP_SELF] > conf->max_mrru[PPP_SELF]
        !           298:              || conf->min_mrru[PPP_PEER] > conf->max_mrru[PPP_PEER])) {
        !           299:                errno = EINVAL;
        !           300:                goto fail;
        !           301:        }
        !           302: 
        !           303:        /* Sanity check EID */
        !           304:        if (conf->eid.class >= PPP_EID_CLASS_MAX
        !           305:            || conf->eid.length < eid_types[conf->eid.class].min
        !           306:            || conf->eid.length > eid_types[conf->eid.class].max) {
        !           307:                errno = EINVAL;
        !           308:                goto fail;
        !           309:        }
        !           310: 
        !           311:        /*
        !           312:         * At least one type of authentication (including "none")
        !           313:         * must be enabled in each direction.
        !           314:         */
        !           315:        nauth[PPP_SELF] = 0;
        !           316:        nauth[PPP_PEER] = 0;
        !           317:        for (i = 0; i < PPP_AUTH_MAX; i++) {
        !           318:                if (conf->auth[PPP_SELF][i] != 0)
        !           319:                        nauth[PPP_SELF]++;
        !           320:                if (conf->auth[PPP_PEER][i] != 0)
        !           321:                        nauth[PPP_PEER]++;
        !           322:        }
        !           323:        if (nauth[PPP_SELF] == 0 || nauth[PPP_PEER] == 0) {
        !           324:                errno = EINVAL;
        !           325:                goto fail;
        !           326:        }
        !           327: 
        !           328:        /* Initialize local request state */
        !           329:        req = &lcp->req;
        !           330:        req->mru[PPP_SELF] = conf->max_mru[PPP_SELF];
        !           331:        req->accm[PPP_SELF] = conf->accm;
        !           332:        req->magic[PPP_SELF] = random() ^ time(NULL) ^ (getpid() << 16);
        !           333:        req->acfcomp[PPP_SELF] = conf->acfcomp[PPP_SELF];
        !           334:        req->pfcomp[PPP_SELF] = conf->pfcomp[PPP_SELF];
        !           335:        for (i = PPP_AUTH_MAX - 1; i >= 0; i--) {
        !           336:                if (conf->auth[PPP_SELF][i] != 0) {
        !           337:                        req->auth[PPP_SELF] = i;
        !           338:                        break;
        !           339:                }
        !           340:        }
        !           341:        req->multilink[PPP_SELF] = conf->multilink[PPP_SELF];
        !           342:        req->mrru[PPP_SELF] = conf->max_mrru[PPP_SELF];
        !           343:        req->shortseq[PPP_SELF] = conf->shortseq[PPP_SELF];
        !           344:        req->eid[PPP_SELF] = conf->eid;
        !           345: 
        !           346: no_conf:
        !           347:        /* Done */
        !           348:        return (inst);
        !           349: 
        !           350: fail:
        !           351:        /* Clean up after failure */
        !           352:        if (lcp != NULL)
        !           353:                FREE(LCP_MTYPE, lcp);
        !           354:        FREE(LCP_MTYPE, inst);
        !           355:        return (NULL);
        !           356: }
        !           357: 
        !           358: /*
        !           359:  * Get LCP request state.
        !           360:  */
        !           361: void
        !           362: ppp_lcp_get_req(struct ppp_fsm *fsm, struct ppp_lcp_req *req)
        !           363: {
        !           364:        struct ppp_fsm_instance *const inst = ppp_fsm_get_instance(fsm);
        !           365:        struct lcp *const lcp = inst->arg;
        !           366: 
        !           367:        assert(inst->type == &ppp_fsm_lcp
        !           368:            || inst->type == &ppp_fsm_mp_lcp);
        !           369:        memcpy(req, &lcp->req, sizeof(*req));
        !           370: }
        !           371: 
        !           372: /***********************************************************************
        !           373:                        FSM CALLBACKS
        !           374: ***********************************************************************/
        !           375: 
        !           376: static void
        !           377: ppp_lcp_destroy(struct ppp_fsm_instance *inst)
        !           378: {
        !           379:        struct lcp *const lcp = inst->arg;
        !           380: 
        !           381:        FREE(LCP_MTYPE, lcp);
        !           382:        FREE(LCP_MTYPE, inst);
        !           383: }
        !           384: 
        !           385: static int
        !           386: ppp_lcp_build_conf_req(struct ppp_fsm_instance *fsm,
        !           387:        struct ppp_fsm_options *opts)
        !           388: {
        !           389:        struct lcp *const lcp = (struct lcp *)fsm->arg;
        !           390:        struct ppp_lcp_req *const req = &lcp->req;
        !           391:        u_int16_t val16;
        !           392:        u_int32_t val32;
        !           393: 
        !           394:        /* Do MRU, ACCM, ACF compression, PF compression, and magic # */
        !           395:        val16 = htons(req->mru[PPP_SELF]);
        !           396:        if (ppp_fsm_option_add(opts, LCP_OPT_MRU, 2, &val16) == -1)
        !           397:                return (-1);
        !           398:        val32 = htonl(req->accm[PPP_SELF]);
        !           399:        if (ppp_fsm_option_add(opts, LCP_OPT_ACCMAP, 4, &val32) == -1)
        !           400:                return (-1);
        !           401:        if (req->acfcomp[PPP_SELF]
        !           402:            && ppp_fsm_option_add(opts, LCP_OPT_ACFCMP, 0, NULL) == -1)
        !           403:                return (-1);
        !           404:        if (req->pfcomp[PPP_SELF]
        !           405:            && ppp_fsm_option_add(opts, LCP_OPT_PFCMP, 0, NULL) == -1)
        !           406:                return (-1);
        !           407:        val32 = htonl(req->magic[PPP_SELF]);
        !           408:        if (ppp_fsm_option_add(opts, LCP_OPT_MAGIC, 4, &val32) == -1)
        !           409:                return (-1);
        !           410:        if (req->auth[PPP_SELF] != PPP_AUTH_NONE) {
        !           411:                const struct ppp_auth_type *const a
        !           412:                    = ppp_auth_by_index(req->auth[PPP_SELF]);
        !           413: 
        !           414:                if (ppp_fsm_option_add(opts,
        !           415:                    LCP_OPT_AUTH, a->len, a->data) == -1)
        !           416:                        return (-1);
        !           417:        }
        !           418: 
        !           419:        /* Do multi-link stuff */
        !           420:        if (req->multilink[PPP_SELF]) {
        !           421:                val16 = htons(req->mrru[PPP_SELF]);
        !           422:                if (ppp_fsm_option_add(opts, LCP_OPT_MRRU, 2, &val16) == -1)
        !           423:                        return (-1);
        !           424:                if (req->shortseq[PPP_SELF]
        !           425:                    && ppp_fsm_option_add(opts, LCP_OPT_SHSEQ, 0, NULL) == -1)
        !           426:                        return (-1);
        !           427:        }
        !           428: 
        !           429:        /* Do endpoint descriminator */
        !           430:        if (req->eid[PPP_SELF].class != PPP_EID_CLASS_NULL) {
        !           431:                u_char eid_buf[1 + PPP_EID_MAXLEN];
        !           432: 
        !           433:                eid_buf[0] = req->eid[PPP_SELF].class;
        !           434:                memcpy(eid_buf + 1,
        !           435:                    req->eid[PPP_SELF].value, req->eid[PPP_SELF].length);
        !           436:                if (ppp_fsm_option_add(opts, LCP_OPT_EDISC,
        !           437:                    1 + req->eid[PPP_SELF].length, eid_buf) == -1)
        !           438:                        return (-1);
        !           439:        }
        !           440: 
        !           441:        /* Done */
        !           442:        return (0);
        !           443: }
        !           444: 
        !           445: static int
        !           446: ppp_lcp_recv_conf_req(struct ppp_fsm_instance *fsm, struct ppp_fsm_options *crq,
        !           447:        struct ppp_fsm_options *nak, struct ppp_fsm_options *rej)
        !           448: {
        !           449:        struct lcp *const lcp = (struct lcp *)fsm->arg;
        !           450:        struct ppp_lcp_config *const conf = &lcp->conf;
        !           451:        struct ppp_lcp_req *const req = &lcp->req;
        !           452:        int i;
        !           453: 
        !           454:        /* Initialize peer's request state */
        !           455:        req->mru[PPP_PEER] = LCP_DEFAULT_MRU;
        !           456:        req->accm[PPP_PEER] = ~0;
        !           457:        req->acfcomp[PPP_PEER] = 0;
        !           458:        req->pfcomp[PPP_PEER] = 0;
        !           459:        req->magic[PPP_PEER] = 0;
        !           460:        req->auth[PPP_PEER] = PPP_AUTH_NONE;
        !           461:        req->mrru[PPP_PEER] = LCP_DEFAULT_MRRU;
        !           462:        req->multilink[PPP_PEER] = 0;
        !           463:        req->shortseq[PPP_PEER] = 0;
        !           464:        req->eid[PPP_PEER].class = PPP_EID_CLASS_NULL;
        !           465:        req->eid[PPP_PEER].length = 0;
        !           466: 
        !           467:        /* Process options */
        !           468:        for (i = 0; i < crq->num; i++) {
        !           469:                const struct ppp_fsm_option *const opt = &crq->opts[i];
        !           470: 
        !           471:                switch (opt->type) {
        !           472:                case LCP_OPT_MRU:
        !           473:                    {
        !           474:                        u_int16_t mru;
        !           475: 
        !           476:                        memcpy(&mru, opt->data, 2);
        !           477:                        mru = ntohs(mru);
        !           478:                        if (mru < conf->min_mru[PPP_PEER]) {
        !           479:                                mru = htons(conf->min_mru[PPP_PEER]);
        !           480:                                if (ppp_fsm_option_add(nak, opt->type,
        !           481:                                    sizeof(mru), &mru) == -1)
        !           482:                                        return (-1);
        !           483:                                break;
        !           484:                        }
        !           485:                        if (mru > conf->max_mru[PPP_PEER]) {
        !           486:                                mru = htons(conf->max_mru[PPP_PEER]);
        !           487:                                if (ppp_fsm_option_add(nak, opt->type,
        !           488:                                    sizeof(mru), &mru) == -1)
        !           489:                                        return (-1);
        !           490:                                break;
        !           491:                        }
        !           492:                        req->mru[PPP_PEER] = mru;
        !           493:                        break;
        !           494:                    }
        !           495:                case LCP_OPT_ACCMAP:
        !           496:                    {
        !           497:                        memcpy(&req->accm[PPP_PEER], opt->data, 4);
        !           498:                        req->accm[PPP_PEER] = ntohl(req->accm[PPP_PEER]);
        !           499:                        break;
        !           500:                    }
        !           501:                case LCP_OPT_PFCMP:
        !           502:                    {
        !           503:                        if (!conf->pfcomp[PPP_PEER])
        !           504:                                goto reject;
        !           505:                        req->pfcomp[PPP_PEER] = 1;
        !           506:                        break;
        !           507:                    }
        !           508:                case LCP_OPT_ACFCMP:
        !           509:                    {
        !           510:                        if (!conf->acfcomp[PPP_PEER])
        !           511:                                goto reject;
        !           512:                        req->acfcomp[PPP_PEER] = 1;
        !           513:                        break;
        !           514:                    }
        !           515:                case LCP_OPT_MAGIC:
        !           516:                    {
        !           517:                        u_int32_t magic;
        !           518: 
        !           519:                        memcpy(&magic, opt->data, 4);
        !           520:                        magic = ntohl(magic);
        !           521:                        if (magic == req->magic[PPP_SELF]) {
        !           522:                                errno = ELOOP;          /* indicate loopback */
        !           523:                                return (-1);
        !           524:                        }
        !           525:                        req->magic[PPP_PEER] = magic;
        !           526:                        break;
        !           527:                    }
        !           528:                case LCP_OPT_AUTH:
        !           529:                    {
        !           530:                        const struct ppp_auth_type *a = ppp_auth_by_option(opt);
        !           531:                        int i;
        !           532: 
        !           533:                        /* Sanity check */
        !           534:                        if (a == NULL)
        !           535:                                break;
        !           536: 
        !           537:                        /* Check if we accept peer's auth proposal */
        !           538:                        if (conf->auth[PPP_PEER][a->index] != 0) {
        !           539:                                req->auth[PPP_PEER] = a->index;
        !           540:                                break;
        !           541:                        }
        !           542: 
        !           543:                        /* See what other type we can do and nak with it */
        !           544:                        for (i = 1; i < PPP_AUTH_MAX; i++) {
        !           545:                                if (conf->auth[PPP_PEER][i] != 0) {
        !           546:                                        a = ppp_auth_by_index(i);
        !           547:                                        if (ppp_fsm_option_add(nak, opt->type,
        !           548:                                            a->len, a->data) == -1)
        !           549:                                                return (-1);
        !           550:                                        break;
        !           551:                                }
        !           552:                        }
        !           553: 
        !           554:                        /* No auth type is acceptable */
        !           555:                        goto reject;
        !           556:                    }
        !           557:                case LCP_OPT_MRRU:
        !           558:                    {
        !           559:                        u_int16_t mrru;
        !           560: 
        !           561:                        if (!conf->multilink[PPP_PEER])
        !           562:                                goto reject;
        !           563:                        memcpy(&mrru, opt->data, 2);
        !           564:                        mrru = ntohs(mrru);
        !           565:                        if (mrru < conf->min_mrru[PPP_PEER]) {
        !           566:                                mrru = htons(conf->min_mrru[PPP_PEER]);
        !           567:                                if (ppp_fsm_option_add(nak,
        !           568:                                    opt->type, 2, &mrru) == -1)
        !           569:                                        return (-1);
        !           570:                                break;
        !           571:                        }
        !           572:                        if (mrru > conf->max_mrru[PPP_PEER]) {
        !           573:                                mrru = htons(conf->max_mrru[PPP_PEER]);
        !           574:                                if (ppp_fsm_option_add(nak,
        !           575:                                    opt->type, 2, &mrru) == -1)
        !           576:                                        return (-1);
        !           577:                                break;
        !           578:                        }
        !           579:                        req->multilink[PPP_PEER] = 1;
        !           580:                        req->multilink[PPP_SELF] = 1;
        !           581:                        req->mrru[PPP_PEER] = mrru;
        !           582:                        break;
        !           583:                    }
        !           584:                case LCP_OPT_SHSEQ:
        !           585:                    {
        !           586:                        if (!conf->multilink[PPP_PEER]
        !           587:                            || !conf->shortseq[PPP_PEER])
        !           588:                                goto reject;
        !           589:                        req->shortseq[PPP_PEER] = 1;
        !           590:                        break;
        !           591:                    }
        !           592:                case LCP_OPT_EDISC:
        !           593:                    {
        !           594:                        struct ppp_eid eid;
        !           595: 
        !           596:                        if (opt->len < 1)
        !           597:                                goto reject;
        !           598:                        eid.class = opt->data[0];
        !           599:                        eid.length = opt->len - 1;
        !           600:                        if (eid.class >= PPP_EID_CLASS_MAX
        !           601:                            || eid.length < eid_types[eid.class].min
        !           602:                            || eid.length > eid_types[eid.class].max)
        !           603:                                goto reject;
        !           604:                        memcpy(eid.value, opt->data + 1, eid.length);
        !           605:                        req->eid[PPP_PEER] = eid;
        !           606:                        break;
        !           607:                    }
        !           608:                default:
        !           609:                        goto reject;
        !           610:                }
        !           611: 
        !           612:                /* OK */
        !           613:                continue;
        !           614: 
        !           615: reject:
        !           616:                /* Reject this requested option */
        !           617:                if (ppp_fsm_option_add(rej,
        !           618:                    opt->type, opt->len, opt->data) == -1)
        !           619:                        return (-1);
        !           620:        }
        !           621: 
        !           622:        /* If no auth requested, but we require auth, nak for it */
        !           623:        if (req->auth[PPP_PEER] == PPP_AUTH_NONE
        !           624:            && !conf->auth[PPP_PEER][PPP_AUTH_NONE]) {
        !           625:                for (i = 1; i < PPP_AUTH_MAX; i++) {
        !           626:                        if (conf->auth[PPP_PEER][i] != 0) {
        !           627:                                const struct ppp_auth_type *const a
        !           628:                                    = ppp_auth_by_index(i);
        !           629: 
        !           630:                                if (ppp_fsm_option_add(nak,
        !           631:                                    LCP_OPT_AUTH, a->len, a->data) == -1)
        !           632:                                        return (-1);
        !           633:                        }
        !           634:                }
        !           635:        }
        !           636: 
        !           637:        /* Do same for multilink? */
        !           638: 
        !           639:        /* Done */
        !           640:        return (0);
        !           641: }
        !           642: 
        !           643: static int
        !           644: ppp_lcp_recv_conf_rej(struct ppp_fsm_instance *fsm, struct ppp_fsm_options *rej)
        !           645: {
        !           646:        struct lcp *const lcp = (struct lcp *)fsm->arg;
        !           647:        struct ppp_lcp_config *const conf = &lcp->conf;
        !           648:        struct ppp_lcp_req *const req = &lcp->req;
        !           649:        int i;
        !           650: 
        !           651:        for (i = 0; i < rej->num; i++) {
        !           652:                const struct ppp_fsm_option *const opt = &rej->opts[i];
        !           653: 
        !           654:                switch (opt->type) {
        !           655:                case LCP_OPT_MRU:
        !           656:                        req->mru[PPP_SELF] = LCP_DEFAULT_MRU;
        !           657:                        break;
        !           658:                case LCP_OPT_ACCMAP:
        !           659:                        req->accm[PPP_SELF] = ~0;
        !           660:                        break;
        !           661:                case LCP_OPT_PFCMP:
        !           662:                        req->pfcomp[PPP_SELF] = 0;
        !           663:                        break;
        !           664:                case LCP_OPT_ACFCMP:
        !           665:                        req->acfcomp[PPP_SELF] = 0;
        !           666:                        break;
        !           667:                case LCP_OPT_MAGIC:
        !           668:                        req->magic[PPP_SELF] = 0;
        !           669:                        break;
        !           670:                case LCP_OPT_AUTH:
        !           671:                    {
        !           672:                        const struct ppp_auth_type *a = ppp_auth_by_option(opt);
        !           673:                        int i;
        !           674: 
        !           675:                        /* Sanity check */
        !           676:                        if (a == NULL)
        !           677:                                break;
        !           678: 
        !           679:                        /* Mark this auth type as rejected by peer */
        !           680:                        req->auth_rej[a->index] = 1;
        !           681: 
        !           682:                        /* Find next acceptable type not rejected by peer */
        !           683:                        for (i = 0; i < PPP_AUTH_MAX; i++) {
        !           684:                                if (conf->auth[PPP_SELF][i]
        !           685:                                    && !req->auth_rej[i]) {
        !           686:                                        req->auth[PPP_SELF] = i;
        !           687:                                        break;
        !           688:                                }
        !           689:                        }
        !           690: 
        !           691:                        /* None found? Can't continue */
        !           692:                        if (i == PPP_AUTH_MAX) {
        !           693:                                errno = EINVAL;
        !           694:                                return (-1);
        !           695:                        }
        !           696:                        break;
        !           697:                    }
        !           698:                case LCP_OPT_MRRU:
        !           699:                        req->multilink[PPP_SELF] = 0;
        !           700:                        /* fall through */
        !           701:                case LCP_OPT_SHSEQ:
        !           702:                        req->shortseq[PPP_SELF] = 0;
        !           703:                        break;
        !           704:                case LCP_OPT_EDISC:
        !           705:                        req->eid[PPP_SELF].class = PPP_EID_CLASS_NULL;
        !           706:                        req->eid[PPP_SELF].length = 0;
        !           707:                        break;
        !           708:                default:
        !           709:                        break;
        !           710:                }
        !           711:        }
        !           712: 
        !           713:        /* Done */
        !           714:        return (0);
        !           715: }
        !           716: 
        !           717: static int
        !           718: ppp_lcp_recv_conf_nak(struct ppp_fsm_instance *fsm, struct ppp_fsm_options *nak)
        !           719: {
        !           720:        struct lcp *const lcp = (struct lcp *)fsm->arg;
        !           721:        struct ppp_lcp_config *const conf = &lcp->conf;
        !           722:        struct ppp_lcp_req *const req = &lcp->req;
        !           723:        int i;
        !           724: 
        !           725:        for (i = 0; i < nak->num; i++) {
        !           726:                const struct ppp_fsm_option *const opt = &nak->opts[i];
        !           727: 
        !           728:                switch (opt->type) {
        !           729:                case LCP_OPT_MRU:
        !           730:                    {
        !           731:                        u_int16_t mru;
        !           732: 
        !           733:                        memcpy(&mru, opt->data, 2);
        !           734:                        mru = ntohs(mru);
        !           735:                        if (mru < conf->min_mru[PPP_SELF])
        !           736:                                mru = conf->min_mru[PPP_SELF];
        !           737:                        if (mru > conf->max_mru[PPP_SELF])
        !           738:                                mru = conf->max_mru[PPP_SELF];
        !           739:                        req->mru[PPP_SELF] = mru;
        !           740:                        break;
        !           741:                    }
        !           742:                case LCP_OPT_ACCMAP:
        !           743:                    {
        !           744:                        memcpy(&req->accm[PPP_SELF], opt->data, 4);
        !           745:                        req->accm[PPP_SELF] = ntohl(req->accm[PPP_SELF]);
        !           746:                        break;
        !           747:                    }
        !           748:                case LCP_OPT_PFCMP:
        !           749:                    {
        !           750:                        if (conf->pfcomp[PPP_SELF])
        !           751:                                req->pfcomp[PPP_SELF] = 1;
        !           752:                        break;
        !           753:                    }
        !           754:                case LCP_OPT_ACFCMP:
        !           755:                    {
        !           756:                        if (conf->acfcomp[PPP_SELF])
        !           757:                                req->acfcomp[PPP_SELF] = 1;
        !           758:                        break;
        !           759:                    }
        !           760:                case LCP_OPT_AUTH:
        !           761:                    {
        !           762:                        const struct ppp_auth_type *a = ppp_auth_by_option(opt);
        !           763: 
        !           764:                        if (a != NULL && conf->auth[PPP_SELF][a->index])
        !           765:                                req->auth[PPP_SELF] = a->index;
        !           766:                        break;
        !           767:                    }
        !           768:                case LCP_OPT_MRRU:
        !           769:                    {
        !           770:                        u_int16_t mrru;
        !           771: 
        !           772:                        memcpy(&mrru, opt->data, 2);
        !           773:                        mrru = ntohs(mrru);
        !           774:                        if (mrru < conf->min_mrru[PPP_SELF])
        !           775:                                mrru = conf->min_mrru[PPP_SELF];
        !           776:                        if (mrru > conf->max_mrru[PPP_SELF])
        !           777:                                mrru = conf->max_mrru[PPP_SELF];
        !           778:                        req->mrru[PPP_SELF] = mrru;
        !           779:                        break;
        !           780:                    }
        !           781:                case LCP_OPT_SHSEQ:
        !           782:                    {
        !           783:                        if (conf->shortseq[PPP_SELF])
        !           784:                                req->shortseq[PPP_SELF] = 1;
        !           785:                        break;
        !           786:                    }
        !           787:                default:
        !           788:                        break;
        !           789:                }
        !           790:        }
        !           791: 
        !           792:        /* Done */
        !           793:        return (0);
        !           794: }
        !           795: 
        !           796: static u_int32_t
        !           797: ppp_lcp_get_magic(struct ppp_fsm_instance *fsm, int dir)
        !           798: {
        !           799:        struct lcp *const lcp = (struct lcp *)fsm->arg;
        !           800:        struct ppp_lcp_req *const req = &lcp->req;
        !           801: 
        !           802:        return (req->magic[dir]);
        !           803: }
        !           804: 
        !           805: /***********************************************************************
        !           806:                        INTERNAL FUNCTIONS
        !           807: ***********************************************************************/
        !           808: 
        !           809: static void
        !           810: lcp_pr_eid(const struct ppp_fsm_optdesc *desc,
        !           811:        const struct ppp_fsm_option *opt, char *buf, size_t bmax)
        !           812: {
        !           813:        const struct eid_type *type;
        !           814:        struct ppp_eid eid;
        !           815:        int i;
        !           816: 
        !           817:        if (opt->len < 1) {
        !           818:                strlcpy(buf, "<truncated>", bmax);
        !           819:                return;
        !           820:        }
        !           821:        eid.class = opt->data[0];
        !           822:        if (eid.class >= PPP_EID_CLASS_MAX) {
        !           823:                snprintf(buf, bmax, "<invalid class %u>", eid.class);
        !           824:                return;
        !           825:        }
        !           826:        type = &eid_types[eid.class];
        !           827:        eid.length = opt->len - 1;
        !           828:        if (eid.length < type->min || eid.length > type->max) {
        !           829:                snprintf(buf, bmax,
        !           830:                    "[%s] <invalid length %d>", type->desc, eid.length);
        !           831:                return;
        !           832:        }
        !           833:        memcpy(eid.value, opt->data + 1, eid.length);
        !           834:        snprintf(buf, bmax, "%s:", type->desc);
        !           835:        switch (eid.class) {
        !           836:        case PPP_EID_CLASS_NULL:
        !           837:                break;
        !           838:        case PPP_EID_CLASS_IP:
        !           839:            {
        !           840:                struct in_addr ip;
        !           841: 
        !           842:                memcpy(&ip, eid.value, sizeof(ip));
        !           843:                strlcpy(buf + strlen(buf), inet_ntoa(ip), bmax - strlen(buf));
        !           844:                break;
        !           845:            }
        !           846:        case PPP_EID_CLASS_LOCAL:
        !           847:                for (i = 0; i < eid.length
        !           848:                    && (isprint(eid.value[i]) || isspace(eid.value[i])); i++);
        !           849:                if (i == eid.length) {
        !           850:                        ppp_util_ascify(buf + strlen(buf),
        !           851:                            bmax - strlen(buf), eid.value, eid.length);
        !           852:                        break;
        !           853:                }
        !           854:                /* FALL THROUGH */
        !           855:        default:
        !           856:                for (i = 0; i < eid.length; i++) {
        !           857:                        snprintf(buf + strlen(buf), bmax - strlen(buf),
        !           858:                            "%s%02x", (i > 0) ? ":" : "", eid.value[i]);
        !           859:                }
        !           860:                break;
        !           861:        }
        !           862: }
        !           863: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>