Annotation of embedaddon/libpdel/ppp/ppp_lcp.c, revision 1.1.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>