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>