Annotation of embedaddon/libpdel/ppp/ppp_ipcp.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_log.h"
! 43: #include "ppp/ppp_fsm_option.h"
! 44: #include "ppp/ppp_fsm.h"
! 45: #include "ppp/ppp_auth.h"
! 46: #include "ppp/ppp_ipcp.h"
! 47:
! 48: /* Whether to do VJC compressed CID's */
! 49: #define IPCP_ALLOW_SELF_COMPCID 0 /* whether we allow to recv */
! 50: #define IPCP_ALLOW_PEER_COMPCID 1 /* whether we allow to send */
! 51:
! 52: /* Memory type */
! 53: #define IPCP_MTYPE "ipcp"
! 54:
! 55: /* IPCP configuration options */
! 56: enum ipcp_option {
! 57: IPCP_OPT_IP =3, /* ip address */
! 58: IPCP_OPT_COMP =2, /* compression */
! 59: IPCP_OPT_DNS1 =129, /* primary dns */
! 60: IPCP_OPT_DNS2 =131, /* secondary dns */
! 61: IPCP_OPT_NBNS1 =130, /* primary nbns */
! 62: IPCP_OPT_NBNS2 =132, /* secondary nbns */
! 63: };
! 64:
! 65: static const u_char ipcp_dns_opts[2] = { IPCP_OPT_DNS1, IPCP_OPT_DNS2 };
! 66: static const u_char ipcp_nbns_opts[2] = { IPCP_OPT_NBNS1, IPCP_OPT_NBNS2 };
! 67:
! 68: /* Supported and required FSM codes */
! 69: #define IPCP_SUPPORTED_CODES \
! 70: (1 << FSM_CODE_CONFIGREQ) \
! 71: | (1 << FSM_CODE_CONFIGACK) \
! 72: | (1 << FSM_CODE_CONFIGNAK) \
! 73: | (1 << FSM_CODE_CONFIGREJ) \
! 74: | (1 << FSM_CODE_TERMREQ) \
! 75: | (1 << FSM_CODE_TERMACK) \
! 76: | (1 << FSM_CODE_CODEREJ)
! 77: #define IPCP_REQUIRED_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:
! 86: /* FSM options descriptors */
! 87: static opt_pr_t ppp_ipcp_pr_ip;
! 88: static opt_pr_t ppp_ipcp_pr_ipcomp;
! 89:
! 90: static const struct ppp_fsm_optdesc ipcp_opt_desc[] = {
! 91: { "IP-Addr", IPCP_OPT_IP, 4, 4, 1, ppp_ipcp_pr_ip },
! 92: { "IP-Comp", IPCP_OPT_COMP, 4, 4, 1, ppp_ipcp_pr_ipcomp },
! 93: { "DNS1", IPCP_OPT_DNS1, 4, 4, 1, ppp_ipcp_pr_ip },
! 94: { "DNS2", IPCP_OPT_DNS2, 4, 4, 1, ppp_ipcp_pr_ip },
! 95: { "NBNS1", IPCP_OPT_NBNS1, 4, 4, 1, ppp_ipcp_pr_ip },
! 96: { "NBNS2", IPCP_OPT_NBNS2, 4, 4, 1, ppp_ipcp_pr_ip },
! 97: { NULL, 0, 0, 0, 0, NULL }
! 98: };
! 99:
! 100: /* FSM type for IPCP */
! 101: static ppp_fsm_type_destroy_t ppp_ipcp_destroy;
! 102: static ppp_fsm_type_build_conf_req_t ppp_ipcp_build_conf_req;
! 103: static ppp_fsm_type_recv_conf_req_t ppp_ipcp_recv_conf_req;
! 104: static ppp_fsm_type_recv_conf_rej_t ppp_ipcp_recv_conf_rej;
! 105: static ppp_fsm_type_recv_conf_nak_t ppp_ipcp_recv_conf_nak;
! 106:
! 107: const struct ppp_fsm_type ppp_fsm_ipcp = {
! 108: "IPCP",
! 109: PPP_PROTO_IPCP,
! 110: IPCP_SUPPORTED_CODES,
! 111: IPCP_REQUIRED_CODES,
! 112: ipcp_opt_desc,
! 113: NULL,
! 114: ppp_ipcp_destroy,
! 115: ppp_ipcp_build_conf_req,
! 116: ppp_ipcp_recv_conf_req,
! 117: ppp_ipcp_recv_conf_rej,
! 118: ppp_ipcp_recv_conf_nak,
! 119: NULL,
! 120: NULL,
! 121: NULL,
! 122: NULL
! 123: };
! 124:
! 125: /* IPCP instance state */
! 126: struct ipcp {
! 127: struct ppp_ipcp_config conf; /* initial config */
! 128: struct ppp_ipcp_req req; /* current request state */
! 129: struct ppp_node *node; /* ng_ppp(4) node */
! 130: };
! 131:
! 132: /* VJC compression header */
! 133: struct ipcp_vjc {
! 134: u_int16_t proto;
! 135: u_char maxchan;
! 136: u_char compcid;
! 137: };
! 138:
! 139: /***********************************************************************
! 140: PUBLIC FUNCTIONS
! 141: ***********************************************************************/
! 142:
! 143: struct ppp_fsm_instance *
! 144: ppp_ipcp_create(struct ppp_ipcp_config *conf, struct ppp_node *node)
! 145: {
! 146: struct ppp_fsm_instance *inst;
! 147: struct ppp_ipcp_req *req;
! 148: struct ipcp *ipcp = NULL;
! 149:
! 150: /* Construct instance object */
! 151: if ((inst = MALLOC(IPCP_MTYPE, sizeof(*inst))) == NULL)
! 152: return (NULL);
! 153: memset(inst, 0, sizeof(*inst));
! 154: inst->type = &ppp_fsm_ipcp;
! 155:
! 156: /* Attach private data */
! 157: if ((ipcp = MALLOC(IPCP_MTYPE, sizeof(*ipcp))) == NULL)
! 158: goto fail;
! 159: memset(ipcp, 0, sizeof(*ipcp));
! 160: ipcp->conf = *conf;
! 161: ipcp->node = node;
! 162: inst->arg = ipcp;
! 163:
! 164: /* Initialize local request state */
! 165: req = &ipcp->req;
! 166: req->ip[PPP_SELF] = conf->ip[PPP_SELF];
! 167: req->vjc[PPP_SELF].enabled = 1;
! 168: req->vjc[PPP_SELF].maxchan = NG_VJC_MAX_CHANNELS - 1;
! 169: req->vjc[PPP_SELF].compcid = IPCP_ALLOW_SELF_COMPCID;
! 170: req->ask_dns = conf->do_dns[PPP_SELF];
! 171: req->ask_nbns = conf->do_nbns[PPP_SELF];
! 172:
! 173: /* Done */
! 174: return (inst);
! 175:
! 176: fail:
! 177: /* Clean up after failure */
! 178: if (ipcp != NULL)
! 179: FREE(IPCP_MTYPE, ipcp);
! 180: FREE(IPCP_MTYPE, inst);
! 181: return (NULL);
! 182: }
! 183:
! 184: /*
! 185: * Get IPCP request state.
! 186: */
! 187: void
! 188: ppp_ipcp_get_req(struct ppp_fsm *fsm, struct ppp_ipcp_req *req)
! 189: {
! 190: struct ppp_fsm_instance *const inst = ppp_fsm_get_instance(fsm);
! 191: struct ipcp *const ipcp = inst->arg;
! 192:
! 193: assert(inst->type == &ppp_fsm_ipcp);
! 194: memcpy(req, &ipcp->req, sizeof(*req));
! 195: }
! 196:
! 197: /***********************************************************************
! 198: FSM CALLBACKS
! 199: ***********************************************************************/
! 200:
! 201: static void
! 202: ppp_ipcp_destroy(struct ppp_fsm_instance *inst)
! 203: {
! 204: struct ipcp *const ipcp = inst->arg;
! 205:
! 206: FREE(IPCP_MTYPE, ipcp);
! 207: FREE(IPCP_MTYPE, inst);
! 208: }
! 209:
! 210: static int
! 211: ppp_ipcp_build_conf_req(struct ppp_fsm_instance *fsm,
! 212: struct ppp_fsm_options *opts)
! 213: {
! 214: struct ipcp *const ipcp = (struct ipcp *)fsm->arg;
! 215: struct ppp_ipcp_req *const req = &ipcp->req;
! 216: int i;
! 217:
! 218: /* Add requested config options */
! 219: if (ppp_fsm_option_add(opts, IPCP_OPT_IP, 4, &req->ip[PPP_SELF]) == -1)
! 220: return (-1);
! 221: if (req->vjc[PPP_SELF].enabled) {
! 222: struct ipcp_vjc vjc;
! 223:
! 224: vjc.proto = htons(PPP_PROTO_VJCOMP);
! 225: vjc.maxchan = req->vjc[PPP_SELF].maxchan;
! 226: vjc.compcid = req->vjc[PPP_SELF].compcid;
! 227: if (ppp_fsm_option_add(opts,
! 228: IPCP_OPT_COMP, sizeof(vjc), &vjc) == -1)
! 229: return (-1);
! 230: }
! 231: if (req->ask_dns) {
! 232: for (i = 0; i < 2; i++) {
! 233: if (ppp_fsm_option_add(opts,
! 234: ipcp_dns_opts[i], 4, &req->dns[i]) == -1)
! 235: return (-1);
! 236: }
! 237: }
! 238: if (req->ask_nbns) {
! 239: for (i = 0; i < 2; i++) {
! 240: if (ppp_fsm_option_add(opts,
! 241: ipcp_nbns_opts[i], 4, &req->nbns[i]) == -1)
! 242: return (-1);
! 243: }
! 244: }
! 245:
! 246: /* Done */
! 247: return (0);
! 248: }
! 249:
! 250: static int
! 251: ppp_ipcp_recv_conf_req(struct ppp_fsm_instance *fsm,
! 252: struct ppp_fsm_options *crq, struct ppp_fsm_options *nak,
! 253: struct ppp_fsm_options *rej)
! 254: {
! 255: struct ipcp *const ipcp = (struct ipcp *)fsm->arg;
! 256: struct ppp_ipcp_config *const conf = &ipcp->conf;
! 257: struct ppp_ipcp_req *const req = &ipcp->req;
! 258: int saw_ip = 0;
! 259: int i;
! 260:
! 261: /* Initialize peer's request state */
! 262: req->ip[PPP_PEER].s_addr = 0;
! 263: memset(&req->vjc[PPP_PEER], 0, sizeof(req->vjc[PPP_PEER]));
! 264:
! 265: /* Process options */
! 266: for (i = 0; i < crq->num; i++) {
! 267: const struct ppp_fsm_option *const opt = &crq->opts[i];
! 268:
! 269: switch (opt->type) {
! 270: case IPCP_OPT_IP:
! 271: {
! 272: struct in_addr ip;
! 273:
! 274: saw_ip = 1;
! 275: memcpy(&ip, opt->data, 4);
! 276: if ((ip.s_addr & conf->mask[PPP_PEER].s_addr)
! 277: != (conf->ip[PPP_PEER].s_addr
! 278: & conf->mask[PPP_PEER].s_addr)) {
! 279: if (ppp_fsm_option_add(nak, opt->type,
! 280: 4, &conf->ip[PPP_PEER]) == -1)
! 281: return (-1);
! 282: break;
! 283: }
! 284: req->ip[PPP_PEER] = ip;
! 285: break;
! 286: }
! 287: case IPCP_OPT_COMP:
! 288: {
! 289: struct ipcp_vjc vjc;
! 290: int nakit = 0;
! 291:
! 292: memcpy(&vjc, opt->data, sizeof(vjc));
! 293: if (ntohs(vjc.proto) != PPP_PROTO_VJCOMP)
! 294: goto reject;
! 295: if (vjc.maxchan < NG_VJC_MIN_CHANNELS - 1) {
! 296: vjc.maxchan = NG_VJC_MIN_CHANNELS - 1;
! 297: nakit = 1;
! 298: }
! 299: if (vjc.maxchan > NG_VJC_MAX_CHANNELS - 1) {
! 300: vjc.maxchan = NG_VJC_MAX_CHANNELS - 1;
! 301: nakit = 1;
! 302: }
! 303: #if !IPCP_ALLOW_PEER_COMPCID
! 304: if (vjc.compcid) {
! 305: vjc.compcid = 0;
! 306: nakit = 1;
! 307: }
! 308: #endif
! 309: if (nakit) {
! 310: if (ppp_fsm_option_add(nak,
! 311: opt->type, sizeof(vjc), &vjc) == -1)
! 312: return (-1);
! 313: break;
! 314: }
! 315: req->vjc[PPP_PEER].enabled = 1;
! 316: req->vjc[PPP_PEER].maxchan = vjc.maxchan;
! 317: req->vjc[PPP_PEER].compcid = vjc.compcid;
! 318: break;
! 319: }
! 320: case IPCP_OPT_DNS1:
! 321: case IPCP_OPT_DNS2:
! 322: {
! 323: const int i = (opt->type == IPCP_OPT_DNS2);
! 324: struct in_addr ip;
! 325:
! 326: if (!conf->do_dns[PPP_PEER]
! 327: || conf->dns[i].s_addr == 0)
! 328: goto reject;
! 329: memcpy(&ip, opt->data, 4);
! 330: if (ip.s_addr != conf->dns[i].s_addr) {
! 331: if (ppp_fsm_option_add(nak, opt->type,
! 332: 4, &conf->dns[i]) == -1)
! 333: return (-1);
! 334: break;
! 335: }
! 336: break;
! 337: }
! 338: case IPCP_OPT_NBNS1:
! 339: case IPCP_OPT_NBNS2:
! 340: {
! 341: const int i = (opt->type == IPCP_OPT_NBNS2);
! 342: struct in_addr ip;
! 343:
! 344: if (!conf->do_nbns[PPP_PEER]
! 345: || conf->nbns[i].s_addr == 0)
! 346: goto reject;
! 347: memcpy(&ip, opt->data, 4);
! 348: if (ip.s_addr != conf->nbns[i].s_addr) {
! 349: if (ppp_fsm_option_add(nak, opt->type,
! 350: 4, &conf->nbns[i]) == -1)
! 351: return (-1);
! 352: break;
! 353: }
! 354: break;
! 355: }
! 356: default:
! 357: goto reject;
! 358: }
! 359:
! 360: /* OK */
! 361: continue;
! 362:
! 363: reject:
! 364: /* Reject this requested option */
! 365: if (ppp_fsm_option_add(rej,
! 366: opt->type, opt->len, opt->data) == -1)
! 367: return (-1);
! 368: }
! 369:
! 370: /* Make sure we saw an IP address option */
! 371: if (!saw_ip) {
! 372: errno = EINVAL;
! 373: return (-1);
! 374: }
! 375:
! 376: /* Done */
! 377: return (0);
! 378: }
! 379:
! 380: static int
! 381: ppp_ipcp_recv_conf_rej(struct ppp_fsm_instance *fsm,
! 382: struct ppp_fsm_options *rej)
! 383: {
! 384: struct ipcp *const ipcp = (struct ipcp *)fsm->arg;
! 385: struct ppp_ipcp_req *const req = &ipcp->req;
! 386: int i;
! 387:
! 388: for (i = 0; i < rej->num; i++) {
! 389: const struct ppp_fsm_option *const opt = &rej->opts[i];
! 390:
! 391: switch (opt->type) {
! 392: case IPCP_OPT_IP:
! 393: errno = EINVAL;
! 394: return (-1);
! 395: case IPCP_OPT_COMP:
! 396: req->vjc[PPP_SELF].enabled = 0;
! 397: break;
! 398: case IPCP_OPT_DNS1:
! 399: case IPCP_OPT_DNS2:
! 400: req->ask_dns = 0;
! 401: break;
! 402: case IPCP_OPT_NBNS1:
! 403: case IPCP_OPT_NBNS2:
! 404: req->ask_nbns = 0;
! 405: break;
! 406: default:
! 407: break;
! 408: }
! 409: }
! 410:
! 411: /* Done */
! 412: return (0);
! 413: }
! 414:
! 415: static int
! 416: ppp_ipcp_recv_conf_nak(struct ppp_fsm_instance *fsm,
! 417: struct ppp_fsm_options *nak)
! 418: {
! 419: struct ipcp *const ipcp = (struct ipcp *)fsm->arg;
! 420: struct ppp_ipcp_config *const conf = &ipcp->conf;
! 421: struct ppp_ipcp_req *const req = &ipcp->req;
! 422: int i;
! 423:
! 424: for (i = 0; i < nak->num; i++) {
! 425: const struct ppp_fsm_option *const opt = &nak->opts[i];
! 426:
! 427: switch (opt->type) {
! 428: case IPCP_OPT_IP:
! 429: {
! 430: struct in_addr ip;
! 431:
! 432: memcpy(&ip, opt->data, 4);
! 433: if ((ip.s_addr & conf->mask[PPP_SELF].s_addr)
! 434: != (conf->ip[PPP_SELF].s_addr
! 435: & conf->mask[PPP_SELF].s_addr))
! 436: break;
! 437: req->ip[PPP_SELF] = ip;
! 438: break;
! 439: }
! 440: case IPCP_OPT_COMP:
! 441: {
! 442: struct ipcp_vjc vjc;
! 443:
! 444: memcpy(&vjc, opt->data, sizeof(vjc));
! 445: if (ntohs(vjc.proto) != PPP_PROTO_VJCOMP)
! 446: break;
! 447: if (vjc.maxchan < NG_VJC_MIN_CHANNELS - 1)
! 448: vjc.maxchan = NG_VJC_MIN_CHANNELS - 1;
! 449: if (vjc.maxchan > NG_VJC_MAX_CHANNELS - 1)
! 450: vjc.maxchan = NG_VJC_MAX_CHANNELS - 1;
! 451: req->vjc[PPP_SELF].maxchan = vjc.maxchan;
! 452: #if IPCP_ALLOW_SELF_COMPCID
! 453: if (vjc.compcid)
! 454: req->vjc[PPP_SELF].compcid = 1;
! 455: #endif
! 456: break;
! 457: }
! 458: case IPCP_OPT_DNS1:
! 459: case IPCP_OPT_DNS2:
! 460: {
! 461: const int i = (opt->type == IPCP_OPT_DNS2);
! 462:
! 463: memcpy(&req->dns[i], opt->data, 4);
! 464: break;
! 465: }
! 466: case IPCP_OPT_NBNS1:
! 467: case IPCP_OPT_NBNS2:
! 468: {
! 469: const int i = (opt->type == IPCP_OPT_NBNS2);
! 470:
! 471: memcpy(&req->nbns[i], opt->data, 4);
! 472: break;
! 473: }
! 474: default:
! 475: break;
! 476: }
! 477: }
! 478:
! 479: /* Done */
! 480: return (0);
! 481: }
! 482:
! 483: /***********************************************************************
! 484: INTERNAL FUNCTIONS
! 485: ***********************************************************************/
! 486:
! 487: static void
! 488: ppp_ipcp_pr_ip(const struct ppp_fsm_optdesc *desc,
! 489: const struct ppp_fsm_option *opt, char *buf, size_t bmax)
! 490: {
! 491: struct in_addr ip;
! 492:
! 493: if (opt->len < 4) {
! 494: snprintf(buf, bmax, "<truncated>");
! 495: return;
! 496: }
! 497: memcpy(&ip, opt->data, 4);
! 498: snprintf(buf, bmax, "%s", inet_ntoa(ip));
! 499: }
! 500:
! 501: static void
! 502: ppp_ipcp_pr_ipcomp(const struct ppp_fsm_optdesc *desc,
! 503: const struct ppp_fsm_option *opt, char *buf, size_t bmax)
! 504: {
! 505: struct ipcp_vjc vjc;
! 506:
! 507: if (opt->len < 2) {
! 508: snprintf(buf, bmax, "<truncated>");
! 509: return;
! 510: }
! 511: memcpy(&vjc, opt->data, 2);
! 512: if (ntohs(vjc.proto) != PPP_PROTO_VJCOMP) {
! 513: snprintf(buf, bmax, "?0x%04x", ntohs(vjc.proto));
! 514: return;
! 515: }
! 516: if (opt->len < sizeof(vjc)) {
! 517: snprintf(buf, bmax, "VJCOMP %s", "<truncated>");
! 518: return;
! 519: }
! 520: memcpy(&vjc, opt->data, sizeof(vjc));
! 521: snprintf(buf, bmax, "VJCOMP %d channels, %s comp-cid",
! 522: vjc.maxchan + 1, vjc.compcid ? "allow" : "no");
! 523: }
! 524:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>