Annotation of embedaddon/mpd/src/ipcp.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * ipcp.c
! 4: *
! 5: * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
! 6: * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
! 7: * See ``COPYRIGHT.iij''
! 8: *
! 9: * Rewritten by Archie Cobbs <archie@freebsd.org>
! 10: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
! 11: * See ``COPYRIGHT.whistle''
! 12: */
! 13:
! 14: #include "ppp.h"
! 15: #include "ipcp.h"
! 16: #include "fsm.h"
! 17: #include "ip.h"
! 18: #include "iface.h"
! 19: #include "msg.h"
! 20: #include "ngfunc.h"
! 21: #include "ippool.h"
! 22: #include "util.h"
! 23:
! 24: #include <netgraph.h>
! 25: #include <sys/mbuf.h>
! 26: #ifdef USE_NG_VJC
! 27: #include <net/slcompress.h>
! 28: #include <netgraph/ng_vjc.h>
! 29: #endif
! 30:
! 31: /*
! 32: * DEFINITIONS
! 33: */
! 34:
! 35: #define IPCP_KNOWN_CODES ( (1 << CODE_CONFIGREQ) \
! 36: | (1 << CODE_CONFIGACK) \
! 37: | (1 << CODE_CONFIGNAK) \
! 38: | (1 << CODE_CONFIGREJ) \
! 39: | (1 << CODE_TERMREQ) \
! 40: | (1 << CODE_TERMACK) \
! 41: | (1 << CODE_CODEREJ) )
! 42:
! 43: #define TY_IPADDRS 1
! 44: #define TY_COMPPROTO 2
! 45: #define TY_IPADDR 3
! 46: #define TY_PRIMARYDNS 129
! 47: #define TY_PRIMARYNBNS 130
! 48: #define TY_SECONDARYDNS 131
! 49: #define TY_SECONDARYNBNS 132
! 50:
! 51: /* Keep sync with above */
! 52: #define o2b(x) (((x)<128)?(x):(x)-128+3)
! 53:
! 54: #define IPCP_REJECTED(p,x) ((p)->peer_reject & (1<<o2b(x)))
! 55: #define IPCP_PEER_REJ(p,x) do{(p)->peer_reject |= (1<<o2b(x));}while(0)
! 56:
! 57: #ifdef USE_NG_VJC
! 58: #define IPCP_VJCOMP_MIN_MAXCHAN (NG_VJC_MIN_CHANNELS - 1)
! 59: #define IPCP_VJCOMP_MAX_MAXCHAN (NG_VJC_MAX_CHANNELS - 1)
! 60: #define IPCP_VJCOMP_DEFAULT_MAXCHAN IPCP_VJCOMP_MAX_MAXCHAN
! 61: #endif
! 62:
! 63: /* Set menu options */
! 64: enum {
! 65: SET_RANGES,
! 66: SET_ENABLE,
! 67: SET_DNS,
! 68: SET_NBNS,
! 69: SET_DISABLE,
! 70: SET_ACCEPT,
! 71: SET_DENY,
! 72: SET_YES,
! 73: SET_NO
! 74: };
! 75:
! 76: /*
! 77: * INTERNAL FUNCTIONS
! 78: */
! 79:
! 80: static void IpcpConfigure(Fsm fp);
! 81: static void IpcpUnConfigure(Fsm fp);
! 82:
! 83: static u_char *IpcpBuildConfigReq(Fsm fp, u_char *cp);
! 84: static void IpcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode);
! 85: static void IpcpLayerStart(Fsm fp);
! 86: static void IpcpLayerFinish(Fsm fp);
! 87: static void IpcpLayerUp(Fsm fp);
! 88: static void IpcpLayerDown(Fsm fp);
! 89: static void IpcpFailure(Fsm fp, enum fsmfail reason);
! 90:
! 91: #ifdef USE_NG_VJC
! 92: static int IpcpNgInitVJ(Bund b);
! 93: static void IpcpNgShutdownVJ(Bund b);
! 94: #endif
! 95:
! 96: static int IpcpSetCommand(Context ctx, int ac, char *av[], void *arg);
! 97:
! 98: /*
! 99: * GLOBAL VARIABLES
! 100: */
! 101:
! 102: const struct cmdtab IpcpSetCmds[] = {
! 103: { "ranges {self}[/{width}]|ippool {pool} {peer}[/{width}]|ippool {pool}", "Allowed IP address ranges",
! 104: IpcpSetCommand, NULL, 2, (void *) SET_RANGES },
! 105: { "enable [opt ...]", "Enable option",
! 106: IpcpSetCommand, NULL, 2, (void *) SET_ENABLE},
! 107: { "dns primary [secondary]", "Set peer DNS servers",
! 108: IpcpSetCommand, NULL, 2, (void *) SET_DNS},
! 109: { "nbns primary [secondary]", "Set peer NBNS servers",
! 110: IpcpSetCommand, NULL, 2, (void *) SET_NBNS},
! 111: { "disable [opt ...]", "Disable option",
! 112: IpcpSetCommand, NULL, 2, (void *) SET_DISABLE},
! 113: { "accept [opt ...]", "Accept option",
! 114: IpcpSetCommand, NULL, 2, (void *) SET_ACCEPT},
! 115: { "deny [opt ...]", "Deny option",
! 116: IpcpSetCommand, NULL, 2, (void *) SET_DENY},
! 117: { "yes [opt ...]", "Enable and accept option",
! 118: IpcpSetCommand, NULL, 2, (void *) SET_YES},
! 119: { "no [opt ...]", "Disable and deny option",
! 120: IpcpSetCommand, NULL, 2, (void *) SET_NO},
! 121: { NULL },
! 122: };
! 123:
! 124: /*
! 125: * INTERNAL VARIABLES
! 126: */
! 127:
! 128: static const struct fsmoptinfo gIpcpConfOpts[] = {
! 129: { "IPADDRS", TY_IPADDRS, 8, 8, FALSE },
! 130: #ifdef USE_NG_VJC
! 131: { "COMPPROTO", TY_COMPPROTO, 4, 4, TRUE },
! 132: #endif
! 133: { "IPADDR", TY_IPADDR, 4, 4, TRUE },
! 134: { "PRIDNS", TY_PRIMARYDNS, 4, 4, TRUE },
! 135: { "PRINBNS", TY_PRIMARYNBNS, 4, 4, TRUE },
! 136: { "SECDNS", TY_SECONDARYDNS, 4, 4, TRUE },
! 137: { "SECNBNS", TY_SECONDARYNBNS, 4, 4, TRUE },
! 138: { NULL }
! 139: };
! 140:
! 141: static const struct confinfo gConfList[] = {
! 142: #ifdef USE_NG_VJC
! 143: { 1, IPCP_CONF_VJCOMP, "vjcomp" },
! 144: #endif
! 145: { 0, IPCP_CONF_REQPRIDNS, "req-pri-dns" },
! 146: { 0, IPCP_CONF_REQSECDNS, "req-sec-dns" },
! 147: { 0, IPCP_CONF_REQPRINBNS, "req-pri-nbns" },
! 148: { 0, IPCP_CONF_REQSECNBNS, "req-sec-nbns" },
! 149: { 0, IPCP_CONF_PRETENDIP, "pretend-ip" },
! 150: { 0, 0, NULL },
! 151: };
! 152:
! 153: static const struct fsmtype gIpcpFsmType = {
! 154: "IPCP",
! 155: PROTO_IPCP,
! 156: IPCP_KNOWN_CODES,
! 157: FALSE,
! 158: LG_IPCP, LG_IPCP2,
! 159: NULL,
! 160: IpcpLayerUp,
! 161: IpcpLayerDown,
! 162: IpcpLayerStart,
! 163: IpcpLayerFinish,
! 164: IpcpBuildConfigReq,
! 165: IpcpDecodeConfig,
! 166: IpcpConfigure,
! 167: IpcpUnConfigure,
! 168: NULL,
! 169: NULL,
! 170: NULL,
! 171: NULL,
! 172: IpcpFailure,
! 173: NULL,
! 174: NULL,
! 175: NULL,
! 176: };
! 177:
! 178: /*
! 179: * IpcpStat()
! 180: */
! 181:
! 182: int
! 183: IpcpStat(Context ctx, int ac, char *av[], void *arg)
! 184: {
! 185: #ifdef USE_NG_VJC
! 186: char path[NG_PATHSIZ];
! 187: #endif
! 188: IpcpState const ipcp = &ctx->bund->ipcp;
! 189: Fsm fp = &ipcp->fsm;
! 190: #ifdef USE_NG_VJC
! 191: union {
! 192: u_char buf[sizeof(struct ng_mesg) + sizeof(struct slcompress)];
! 193: struct ng_mesg reply;
! 194: } u;
! 195: struct slcompress *const sls = (struct slcompress *)(void *)u.reply.data;
! 196: #endif
! 197: char buf[48];
! 198:
! 199: Printf("[%s] %s [%s]\r\n", Pref(fp), Fsm(fp), FsmStateName(fp->state));
! 200: Printf("Allowed IP address ranges:\r\n");
! 201: if (ipcp->conf.self_ippool[0]) {
! 202: Printf("\tPeer: ippool %s\r\n",
! 203: ipcp->conf.self_ippool);
! 204: } else {
! 205: Printf("\tSelf: %s\r\n",
! 206: u_rangetoa(&ipcp->conf.self_allow,buf,sizeof(buf)));
! 207: }
! 208: if (ipcp->conf.ippool[0]) {
! 209: Printf("\tPeer: ippool %s\r\n",
! 210: ipcp->conf.ippool);
! 211: } else {
! 212: Printf("\tPeer: %s\r\n",
! 213: u_rangetoa(&ipcp->conf.peer_allow,buf,sizeof(buf)));
! 214: }
! 215: Printf("IPCP Options:\r\n");
! 216: OptStat(ctx, &ipcp->conf.options, gConfList);
! 217: Printf("Current addressing:\r\n");
! 218: Printf("\tSelf: %s\r\n", inet_ntoa(ipcp->want_addr));
! 219: Printf("\tPeer: %s\r\n", inet_ntoa(ipcp->peer_addr));
! 220: #ifdef USE_NG_VJC
! 221: Printf("Compression:\r\n");
! 222: Printf("\tSelf: ");
! 223: if (ipcp->want_comp.proto != 0)
! 224: Printf("%s, %d compression channels, CID %scompressible\r\n",
! 225: ProtoName(ntohs(ipcp->want_comp.proto)),
! 226: ipcp->want_comp.maxchan + 1, ipcp->want_comp.compcid ? "" : "not ");
! 227: else
! 228: Printf("None\r\n");
! 229: Printf("\tPeer: ");
! 230: if (ipcp->peer_comp.proto != 0)
! 231: Printf("%s, %d compression channels, CID %scompressible\n",
! 232: ProtoName(ntohs(ipcp->peer_comp.proto)),
! 233: ipcp->peer_comp.maxchan + 1, ipcp->peer_comp.compcid ? "" : "not ");
! 234: else
! 235: Printf("None\r\n");
! 236: #endif /* USE_NG_VJC */
! 237: Printf("Server info we give to peer:\r\n");
! 238: Printf("DNS servers : %15s", inet_ntoa(ipcp->conf.peer_dns[0]));
! 239: Printf(" %15s\r\n", inet_ntoa(ipcp->conf.peer_dns[1]));
! 240: Printf("NBNS servers: %15s", inet_ntoa(ipcp->conf.peer_nbns[0]));
! 241: Printf(" %15s\r\n", inet_ntoa(ipcp->conf.peer_nbns[1]));
! 242: Printf("Server info peer gave to us:\r\n");
! 243: Printf("DNS servers : %15s", inet_ntoa(ipcp->want_dns[0]));
! 244: Printf(" %15s\r\n", inet_ntoa(ipcp->want_dns[1]));
! 245: Printf("NBNS servers: %15s", inet_ntoa(ipcp->want_nbns[0]));
! 246: Printf(" %15s\r\n", inet_ntoa(ipcp->want_nbns[1]));
! 247:
! 248: #ifdef USE_NG_VJC
! 249: /* Get VJC state */
! 250: snprintf(path, sizeof(path), "mpd%d-%s:%s", gPid, ctx->bund->name, NG_PPP_HOOK_VJC_IP);
! 251: if (NgFuncSendQuery(path, NGM_VJC_COOKIE, NGM_VJC_GET_STATE,
! 252: NULL, 0, &u.reply, sizeof(u), NULL) < 0)
! 253: return(0);
! 254:
! 255: Printf("VJ Compression:\r\n");
! 256: Printf("\tOut comp : %d\r\n", sls->sls_compressed);
! 257: Printf("\tOut total: %d\r\n", sls->sls_packets);
! 258: Printf("\tMissed : %d\r\n", sls->sls_misses);
! 259: Printf("\tSearched : %d\r\n", sls->sls_searches);
! 260: Printf("\tIn comp : %d\r\n", sls->sls_compressedin);
! 261: Printf("\tIn uncomp: %d\r\n", sls->sls_uncompressedin);
! 262: Printf("\tIn error : %d\r\n", sls->sls_errorin);
! 263: Printf("\tIn tossed: %d\r\n", sls->sls_tossed);
! 264: #endif /* USE_NG_VJC */
! 265: return(0);
! 266: }
! 267:
! 268: /*
! 269: * IpcpInit()
! 270: */
! 271:
! 272: void
! 273: IpcpInit(Bund b)
! 274: {
! 275: IpcpState const ipcp = &b->ipcp;
! 276:
! 277: /* Init state machine */
! 278: memset(ipcp, 0, sizeof(*ipcp));
! 279: FsmInit(&ipcp->fsm, &gIpcpFsmType, b);
! 280:
! 281: /* Come up with a default IP address for my side of the link */
! 282: u_rangeclear(&ipcp->conf.self_allow);
! 283: GetAnyIpAddress(&ipcp->conf.self_allow.addr, NULL);
! 284:
! 285: #ifdef USE_NG_VJC
! 286: /* Default we want VJ comp */
! 287: Enable(&ipcp->conf.options, IPCP_CONF_VJCOMP);
! 288: Accept(&ipcp->conf.options, IPCP_CONF_VJCOMP);
! 289: #endif
! 290: }
! 291:
! 292: /*
! 293: * IpcpInst()
! 294: */
! 295:
! 296: void
! 297: IpcpInst(Bund b, Bund bt)
! 298: {
! 299: IpcpState const ipcp = &b->ipcp;
! 300:
! 301: /* Init state machine */
! 302: memcpy(ipcp, &bt->ipcp, sizeof(*ipcp));
! 303: FsmInst(&ipcp->fsm, &bt->ipcp.fsm, b);
! 304: }
! 305:
! 306: /*
! 307: * IpcpConfigure()
! 308: */
! 309:
! 310: static void
! 311: IpcpConfigure(Fsm fp)
! 312: {
! 313: Bund b = (Bund)fp->arg;
! 314: IpcpState const ipcp = &b->ipcp;
! 315: char buf[48];
! 316:
! 317: /* FSM stuff */
! 318: ipcp->peer_reject = 0;
! 319:
! 320: /* Get allowed IP addresses from config and/or from current bundle */
! 321: if (ipcp->conf.self_ippool[0]) {
! 322: if (IPPoolGet(ipcp->conf.self_ippool, &ipcp->self_allow.addr)) {
! 323: Log(LG_IPCP, ("[%s] IPCP: Can't get IP from pool \"%s\" for self",
! 324: b->name, ipcp->conf.self_ippool));
! 325: } else {
! 326: Log(LG_IPCP, ("[%s] IPCP: Got IP %s from pool \"%s\" for self",
! 327: b->name,
! 328: u_addrtoa(&ipcp->self_allow.addr, buf, sizeof(buf)),
! 329: ipcp->conf.self_ippool));
! 330: ipcp->self_allow.width = 32;
! 331: ipcp->self_ippool_used = 1;
! 332: }
! 333: } else
! 334: ipcp->self_allow = ipcp->conf.self_allow;
! 335:
! 336: if ((b->params.range_valid) && (!u_rangeempty(&b->params.range)))
! 337: ipcp->peer_allow = b->params.range;
! 338: else if (b->params.ippool[0]) {
! 339: /* Get IP from pool if needed */
! 340: if (IPPoolGet(b->params.ippool, &ipcp->peer_allow.addr)) {
! 341: Log(LG_IPCP, ("[%s] IPCP: Can't get IP from pool \"%s\" for peer",
! 342: b->name, b->params.ippool));
! 343: } else {
! 344: Log(LG_IPCP, ("[%s] IPCP: Got IP %s from pool \"%s\" for peer",
! 345: b->name,
! 346: u_addrtoa(&ipcp->peer_allow.addr, buf, sizeof(buf)),
! 347: b->params.ippool));
! 348: ipcp->peer_allow.width = 32;
! 349: b->params.ippool_used = 1;
! 350: }
! 351: } else if (ipcp->conf.ippool[0]) {
! 352: if (IPPoolGet(ipcp->conf.ippool, &ipcp->peer_allow.addr)) {
! 353: Log(LG_IPCP, ("[%s] IPCP: Can't get IP from pool \"%s\"",
! 354: b->name, ipcp->conf.ippool));
! 355: } else {
! 356: Log(LG_IPCP, ("[%s] IPCP: Got IP %s from pool \"%s\" for peer",
! 357: b->name,
! 358: u_addrtoa(&ipcp->peer_allow.addr, buf, sizeof(buf)),
! 359: ipcp->conf.ippool));
! 360: ipcp->peer_allow.width = 32;
! 361: ipcp->ippool_used = 1;
! 362: }
! 363: } else
! 364: ipcp->peer_allow = ipcp->conf.peer_allow;
! 365:
! 366: /* Initially request addresses as specified by config */
! 367: u_addrtoin_addr(&ipcp->self_allow.addr, &ipcp->want_addr);
! 368: u_addrtoin_addr(&ipcp->peer_allow.addr, &ipcp->peer_addr);
! 369:
! 370: #ifdef USE_NG_VJC
! 371: /* Van Jacobson compression */
! 372: ipcp->peer_comp.proto = 0;
! 373: ipcp->peer_comp.maxchan = IPCP_VJCOMP_DEFAULT_MAXCHAN;
! 374: ipcp->peer_comp.compcid = 0;
! 375:
! 376: ipcp->want_comp.proto =
! 377: (b->params.vjc_enable || Enabled(&ipcp->conf.options, IPCP_CONF_VJCOMP)) ?
! 378: htons(PROTO_VJCOMP) : 0;
! 379: ipcp->want_comp.maxchan = IPCP_VJCOMP_MAX_MAXCHAN;
! 380:
! 381: /* If any of our links are unable to give receive error indications, we must
! 382: tell the peer not to compress the slot-id in VJCOMP packets (cf. RFC1144).
! 383: To be on the safe side, we always say this. */
! 384: ipcp->want_comp.compcid = 0;
! 385: #endif
! 386:
! 387: /* DNS and NBNS servers */
! 388: memset(&ipcp->want_dns, 0, sizeof(ipcp->want_dns));
! 389: memset(&ipcp->want_nbns, 0, sizeof(ipcp->want_nbns));
! 390: }
! 391:
! 392: /*
! 393: * IpcpUnConfigure()
! 394: */
! 395:
! 396: static void
! 397: IpcpUnConfigure(Fsm fp)
! 398: {
! 399: Bund b = (Bund)fp->arg;
! 400: IpcpState const ipcp = &b->ipcp;
! 401:
! 402: if (ipcp->self_ippool_used) {
! 403: struct u_addr ip;
! 404: in_addrtou_addr(&ipcp->want_addr, &ip);
! 405: IPPoolFree(ipcp->conf.self_ippool, &ip);
! 406: ipcp->self_ippool_used = 0;
! 407: }
! 408: if (b->params.ippool_used) {
! 409: struct u_addr ip;
! 410: in_addrtou_addr(&ipcp->peer_addr, &ip);
! 411: IPPoolFree(b->params.ippool, &ip);
! 412: b->params.ippool_used = 0;
! 413: } else if (ipcp->ippool_used) {
! 414: struct u_addr ip;
! 415: in_addrtou_addr(&ipcp->peer_addr, &ip);
! 416: IPPoolFree(ipcp->conf.ippool, &ip);
! 417: ipcp->ippool_used = 0;
! 418: }
! 419: }
! 420:
! 421: /*
! 422: * IpcpBuildConfigReq()
! 423: */
! 424:
! 425: static u_char *
! 426: IpcpBuildConfigReq(Fsm fp, u_char *cp)
! 427: {
! 428: Bund b = (Bund)fp->arg;
! 429: IpcpState const ipcp = &b->ipcp;
! 430:
! 431: /* Put in my desired IP address */
! 432: if (!IPCP_REJECTED(ipcp, TY_IPADDR) || ipcp->want_addr.s_addr == 0)
! 433: cp = FsmConfValue(cp, TY_IPADDR, 4, &ipcp->want_addr.s_addr);
! 434:
! 435: #ifdef USE_NG_VJC
! 436: /* Put in my requested compression protocol */
! 437: if (ipcp->want_comp.proto != 0 && !IPCP_REJECTED(ipcp, TY_COMPPROTO))
! 438: cp = FsmConfValue(cp, TY_COMPPROTO, 4, &ipcp->want_comp);
! 439: #endif
! 440:
! 441: /* Request peer's DNS and NBNS servers */
! 442: {
! 443: const int sopts[2][2] = { { IPCP_CONF_REQPRIDNS, IPCP_CONF_REQSECDNS },
! 444: { IPCP_CONF_REQPRINBNS, IPCP_CONF_REQSECNBNS }};
! 445: const int nopts[2][2] = { { TY_PRIMARYDNS, TY_SECONDARYDNS },
! 446: { TY_PRIMARYNBNS, TY_SECONDARYNBNS } };
! 447: struct in_addr *vals[2] = { ipcp->want_dns, ipcp->want_nbns };
! 448: int sopt, pri;
! 449:
! 450: for (sopt = 0; sopt < 2; sopt++) {
! 451: for (pri = 0; pri < 2; pri++) {
! 452: const int opt = nopts[sopt][pri];
! 453:
! 454: /* Add option if we desire it and it hasn't been rejected */
! 455: if (Enabled(&ipcp->conf.options, sopts[sopt][pri])
! 456: && !IPCP_REJECTED(ipcp, opt)) {
! 457: cp = FsmConfValue(cp, opt, 4, &vals[sopt][pri]);
! 458: }
! 459: }
! 460: }
! 461: }
! 462:
! 463: /* Done */
! 464:
! 465: return(cp);
! 466: }
! 467:
! 468: /*
! 469: * IpcpLayerStart()
! 470: *
! 471: * Tell the lower layer (the bundle) that we need it
! 472: */
! 473:
! 474: static void
! 475: IpcpLayerStart(Fsm fp)
! 476: {
! 477: BundNcpsStart((Bund)(fp->arg), NCP_IPCP);
! 478: }
! 479:
! 480: /*
! 481: * IpcpLayerFinish()
! 482: *
! 483: * Tell the lower layer (the bundle) that we no longer need it
! 484: */
! 485:
! 486: static void
! 487: IpcpLayerFinish(Fsm fp)
! 488: {
! 489: BundNcpsFinish((Bund)(fp->arg), NCP_IPCP);
! 490: }
! 491:
! 492: /*
! 493: * IpcpLayerUp()
! 494: *
! 495: * Called when IPCP has reached the OPEN state
! 496: */
! 497:
! 498: static void
! 499: IpcpLayerUp(Fsm fp)
! 500: {
! 501: Bund b = (Bund)fp->arg;
! 502: IpcpState const ipcp = &b->ipcp;
! 503: char ipbuf[20];
! 504: #ifdef USE_NG_VJC
! 505: char path[NG_PATHSIZ];
! 506: struct ngm_vjc_config vjc;
! 507: #endif
! 508: struct u_addr tmp;
! 509:
! 510: /* Determine actual address we'll use for ourselves */
! 511: in_addrtou_addr(&ipcp->want_addr, &tmp);
! 512: if (!IpAddrInRange(&ipcp->self_allow, &tmp)) {
! 513: Log(LG_IPCP, ("[%s] Note: ignoring negotiated %s IP %s,",
! 514: b->name, "self", inet_ntoa(ipcp->want_addr)));
! 515: u_addrtoin_addr(&ipcp->self_allow.addr, &ipcp->want_addr);
! 516: Log(LG_IPCP, ("[%s] using %s instead.",
! 517: b->name, inet_ntoa(ipcp->want_addr)));
! 518: }
! 519:
! 520: /* Determine actual address we'll use for peer */
! 521: in_addrtou_addr(&ipcp->peer_addr, &tmp);
! 522: if (!IpAddrInRange(&ipcp->peer_allow, &tmp)
! 523: && !u_addrempty(&ipcp->peer_allow.addr)) {
! 524: Log(LG_IPCP, ("[%s] Note: ignoring negotiated %s IP %s,",
! 525: b->name, "peer", inet_ntoa(ipcp->peer_addr)));
! 526: u_addrtoin_addr(&ipcp->peer_allow.addr, &ipcp->peer_addr);
! 527: Log(LG_IPCP, ("[%s] using %s instead.",
! 528: b->name, inet_ntoa(ipcp->peer_addr)));
! 529: }
! 530:
! 531: /* Report */
! 532: strlcpy(ipbuf, inet_ntoa(ipcp->peer_addr), sizeof(ipbuf));
! 533: Log(LG_IPCP, ("[%s] %s -> %s", b->name, inet_ntoa(ipcp->want_addr), ipbuf));
! 534:
! 535: #ifdef USE_NG_VJC
! 536: memset(&vjc, 0, sizeof(vjc));
! 537: if (ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP ||
! 538: ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP) {
! 539:
! 540: IpcpNgInitVJ(b);
! 541:
! 542: /* Configure VJ compression node */
! 543: vjc.enableComp = ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP;
! 544: vjc.enableDecomp = ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP;
! 545: vjc.maxChannel = ipcp->peer_comp.maxchan;
! 546: vjc.compressCID = ipcp->peer_comp.compcid;
! 547: snprintf(path, sizeof(path), "[%x]:%s", b->nodeID, NG_PPP_HOOK_VJC_IP);
! 548: if (NgSendMsg(gLinksCsock, path,
! 549: NGM_VJC_COOKIE, NGM_VJC_SET_CONFIG, &vjc, sizeof(vjc)) < 0) {
! 550: Perror("[%s] can't config %s node", b->name, NG_VJC_NODE_TYPE);
! 551: }
! 552: }
! 553: #endif /* USE_NG_VJC */
! 554:
! 555: /* Enable IP packets in the PPP node */
! 556: b->pppConfig.bund.enableIP = 1;
! 557: #ifdef USE_NG_VJC
! 558: b->pppConfig.bund.enableVJCompression = vjc.enableComp;
! 559: b->pppConfig.bund.enableVJDecompression = vjc.enableDecomp;
! 560: #endif
! 561: NgFuncSetConfig(b);
! 562:
! 563: BundNcpsJoin(b, NCP_IPCP);
! 564: }
! 565:
! 566: /*
! 567: * IpcpLayerDown()
! 568: *
! 569: * Called when IPCP leaves the OPEN state
! 570: */
! 571:
! 572: static void
! 573: IpcpLayerDown(Fsm fp)
! 574: {
! 575: Bund b = (Bund)fp->arg;
! 576: #ifdef USE_NG_VJC
! 577: IpcpState const ipcp = &b->ipcp;
! 578: #endif
! 579:
! 580: BundNcpsLeave(b, NCP_IPCP);
! 581:
! 582: /* Turn off IP packets */
! 583: b->pppConfig.bund.enableIP = 0;
! 584: #ifdef USE_NG_VJC
! 585: b->pppConfig.bund.enableVJCompression = 0;
! 586: b->pppConfig.bund.enableVJDecompression = 0;
! 587: #endif
! 588: NgFuncSetConfig(b);
! 589:
! 590: #ifdef USE_NG_VJC
! 591: if (ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP ||
! 592: ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP) {
! 593: IpcpNgShutdownVJ(b);
! 594: }
! 595: #endif /* USE_NG_VJC */
! 596: }
! 597:
! 598: /*
! 599: * IpcpUp()
! 600: */
! 601:
! 602: void
! 603: IpcpUp(Bund b)
! 604: {
! 605: FsmUp(&b->ipcp.fsm);
! 606: }
! 607:
! 608: /*
! 609: * IpcpDown()
! 610: */
! 611:
! 612: void
! 613: IpcpDown(Bund b)
! 614: {
! 615: FsmDown(&b->ipcp.fsm);
! 616: }
! 617:
! 618: /*
! 619: * IpcpOpen()
! 620: */
! 621:
! 622: void
! 623: IpcpOpen(Bund b)
! 624: {
! 625: FsmOpen(&b->ipcp.fsm);
! 626: }
! 627:
! 628: /*
! 629: * IpcpClose()
! 630: */
! 631:
! 632: void
! 633: IpcpClose(Bund b)
! 634: {
! 635: FsmClose(&b->ipcp.fsm);
! 636: }
! 637:
! 638: /*
! 639: * IpcpOpenCmd()
! 640: */
! 641:
! 642: int
! 643: IpcpOpenCmd(Context ctx)
! 644: {
! 645: if (ctx->bund->tmpl)
! 646: Error("impossible to open template");
! 647: FsmOpen(&ctx->bund->ipcp.fsm);
! 648: return (0);
! 649: }
! 650:
! 651: /*
! 652: * IpcpCloseCmd()
! 653: */
! 654:
! 655: int
! 656: IpcpCloseCmd(Context ctx)
! 657: {
! 658: if (ctx->bund->tmpl)
! 659: Error("impossible to close template");
! 660: FsmClose(&ctx->bund->ipcp.fsm);
! 661: return (0);
! 662: }
! 663:
! 664: /*
! 665: * IpcpFailure()
! 666: */
! 667:
! 668: static void
! 669: IpcpFailure(Fsm fp, enum fsmfail reason)
! 670: {
! 671: Bund b = (Bund)fp->arg;
! 672: RecordLinkUpDownReason(b, NULL, 0, STR_PROTO_ERR, STR_IPCP_FAILED, FsmFailureStr(reason));
! 673: }
! 674:
! 675: /*
! 676: * IpcpDecodeConfig()
! 677: */
! 678:
! 679: static void
! 680: IpcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
! 681: {
! 682: Bund b = (Bund)fp->arg;
! 683: IpcpState const ipcp = &b->ipcp;
! 684: struct in_addr *wantip, *peerip;
! 685: int k;
! 686:
! 687: /* Decode each config option */
! 688: for (k = 0; k < num; k++) {
! 689: FsmOption const opt = &list[k];
! 690: FsmOptInfo const oi = FsmFindOptInfo(gIpcpConfOpts, opt->type);
! 691:
! 692: if (!oi) {
! 693: Log(LG_IPCP, ("[%s] UNKNOWN[%d] len=%d", b->name, opt->type, opt->len));
! 694: if (mode == MODE_REQ)
! 695: FsmRej(fp, opt);
! 696: continue;
! 697: }
! 698: if (!oi->supported) {
! 699: Log(LG_IPCP, ("[%s] %s", b->name, oi->name));
! 700: if (mode == MODE_REQ) {
! 701: Log(LG_IPCP, ("[%s] Not supported", b->name));
! 702: FsmRej(fp, opt);
! 703: }
! 704: continue;
! 705: }
! 706: if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) {
! 707: Log(LG_IPCP, ("[%s] %s", b->name, oi->name));
! 708: if (mode == MODE_REQ) {
! 709: Log(LG_IPCP, ("[%s] bogus len=%d", b->name, opt->len));
! 710: FsmRej(fp, opt);
! 711: }
! 712: continue;
! 713: }
! 714: switch (opt->type) {
! 715: case TY_IPADDR:
! 716: {
! 717: struct in_addr ip;
! 718: struct u_addr tmp;
! 719:
! 720: memcpy(&ip, opt->data, 4);
! 721: in_addrtou_addr(&ip, &tmp);
! 722: Log(LG_IPCP, ("[%s] %s %s", b->name, oi->name, inet_ntoa(ip)));
! 723: switch (mode) {
! 724: case MODE_REQ:
! 725: if (!IpAddrInRange(&ipcp->peer_allow, &tmp) || !ip.s_addr) {
! 726: if (ipcp->peer_addr.s_addr == 0)
! 727: Log(LG_IPCP, ("[%s] no IP address available for peer!", b->name));
! 728: if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) {
! 729: Log(LG_IPCP, ("[%s] pretending that %s is OK, will ignore",
! 730: b->name, inet_ntoa(ip)));
! 731: ipcp->peer_addr = ip;
! 732: FsmAck(fp, opt);
! 733: break;
! 734: }
! 735: memcpy(opt->data, &ipcp->peer_addr, 4);
! 736: Log(LG_IPCP, ("[%s] NAKing with %s", b->name, inet_ntoa(ipcp->peer_addr)));
! 737: FsmNak(fp, opt);
! 738: break;
! 739: }
! 740: Log(LG_IPCP, ("[%s] %s is OK", b->name, inet_ntoa(ip)));
! 741: ipcp->peer_addr = ip;
! 742: FsmAck(fp, opt);
! 743: break;
! 744: case MODE_NAK:
! 745: {
! 746: if (IpAddrInRange(&ipcp->self_allow, &tmp)) {
! 747: Log(LG_IPCP, ("[%s] %s is OK", b->name, inet_ntoa(ip)));
! 748: ipcp->want_addr = ip;
! 749: } else if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) {
! 750: Log(LG_IPCP, ("[%s] pretending that %s is OK, will ignore",
! 751: b->name, inet_ntoa(ip)));
! 752: ipcp->want_addr = ip;
! 753: } else
! 754: Log(LG_IPCP, ("[%s] %s is unacceptable", b->name, inet_ntoa(ip)));
! 755: }
! 756: break;
! 757: case MODE_REJ:
! 758: IPCP_PEER_REJ(ipcp, opt->type);
! 759: if (ipcp->want_addr.s_addr == 0)
! 760: Log(LG_IPCP, ("[%s] Problem: I need an IP address!", b->name));
! 761: break;
! 762: }
! 763: }
! 764: break;
! 765:
! 766: #ifdef USE_NG_VJC
! 767: case TY_COMPPROTO:
! 768: {
! 769: struct ipcpvjcomp vj;
! 770:
! 771: memcpy(&vj, opt->data, sizeof(vj));
! 772: Log(LG_IPCP, ("[%s] %s %s, %d comp. channels, %s comp-cid",
! 773: b->name, oi->name, ProtoName(ntohs(vj.proto)),
! 774: vj.maxchan + 1, vj.compcid ? "allow" : "no"));
! 775: switch (mode) {
! 776: case MODE_REQ:
! 777: if (!Acceptable(&ipcp->conf.options, IPCP_CONF_VJCOMP) &&
! 778: !b->params.vjc_enable) {
! 779: FsmRej(fp, opt);
! 780: break;
! 781: }
! 782: if (ntohs(vj.proto) == PROTO_VJCOMP
! 783: && vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN
! 784: && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) {
! 785: ipcp->peer_comp = vj;
! 786: FsmAck(fp, opt);
! 787: break;
! 788: }
! 789: vj.proto = htons(PROTO_VJCOMP);
! 790: vj.maxchan = IPCP_VJCOMP_MAX_MAXCHAN;
! 791: vj.compcid = 0;
! 792: memcpy(opt->data, &vj, sizeof(vj));
! 793: FsmNak(fp, opt);
! 794: break;
! 795: case MODE_NAK:
! 796: if (ntohs(vj.proto) != PROTO_VJCOMP) {
! 797: Log(LG_IPCP, ("[%s] Can't accept proto 0x%04x",
! 798: b->name, (u_short) ntohs(vj.proto)));
! 799: break;
! 800: }
! 801: if (vj.maxchan != ipcp->want_comp.maxchan) {
! 802: if (vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN
! 803: && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) {
! 804: Log(LG_IPCP, ("[%s] Adjusting # compression channels", b->name));
! 805: ipcp->want_comp.maxchan = vj.maxchan;
! 806: } else {
! 807: Log(LG_IPCP, ("[%s] Can't handle %d maxchan", b->name, vj.maxchan));
! 808: }
! 809: }
! 810: if (vj.compcid) {
! 811: Log(LG_IPCP, ("[%s] Can't accept comp-cid", b->name));
! 812: break;
! 813: }
! 814: break;
! 815: case MODE_REJ:
! 816: IPCP_PEER_REJ(ipcp, opt->type);
! 817: ipcp->want_comp.proto = 0;
! 818: break;
! 819: }
! 820: }
! 821: break;
! 822: #endif /* USE_NG_VJC */
! 823:
! 824: case TY_PRIMARYDNS:
! 825: if (b->params.peer_dns[0].s_addr != 0)
! 826: peerip = &b->params.peer_dns[0];
! 827: else
! 828: peerip = &ipcp->conf.peer_dns[0];
! 829: wantip = &ipcp->want_dns[0];
! 830: goto doDnsNbns;
! 831: case TY_PRIMARYNBNS:
! 832: if (b->params.peer_nbns[0].s_addr != 0)
! 833: peerip = &b->params.peer_nbns[0];
! 834: else
! 835: peerip = &ipcp->conf.peer_nbns[0];
! 836: wantip = &ipcp->want_nbns[0];
! 837: goto doDnsNbns;
! 838: case TY_SECONDARYDNS:
! 839: if (b->params.peer_dns[1].s_addr != 0)
! 840: peerip = &b->params.peer_dns[1];
! 841: else
! 842: peerip = &ipcp->conf.peer_dns[1];
! 843: wantip = &ipcp->want_dns[1];
! 844: goto doDnsNbns;
! 845: case TY_SECONDARYNBNS:
! 846: if (b->params.peer_nbns[1].s_addr != 0)
! 847: peerip = &b->params.peer_nbns[1];
! 848: else
! 849: peerip = &ipcp->conf.peer_nbns[1];
! 850: wantip = &ipcp->want_nbns[1];
! 851: doDnsNbns:
! 852: {
! 853: struct in_addr hisip;
! 854:
! 855: memcpy(&hisip, opt->data, 4);
! 856: Log(LG_IPCP, ("[%s] %s %s", b->name, oi->name, inet_ntoa(hisip)));
! 857: switch (mode) {
! 858: case MODE_REQ:
! 859: if (hisip.s_addr == 0) { /* he's asking for one */
! 860: if (peerip->s_addr == 0) { /* we don't got one */
! 861: FsmRej(fp, opt);
! 862: break;
! 863: }
! 864: Log(LG_IPCP, ("[%s] NAKing with %s", b->name, inet_ntoa(*peerip)));
! 865: memcpy(opt->data, peerip, sizeof(*peerip));
! 866: FsmNak(fp, opt); /* we got one for him */
! 867: break;
! 868: }
! 869: FsmAck(fp, opt); /* he knows what he wants */
! 870: break;
! 871: case MODE_NAK: /* we asked for his server, he's telling us */
! 872: *wantip = hisip;
! 873: break;
! 874: case MODE_REJ: /* we asked for his server, he's ignorant */
! 875: IPCP_PEER_REJ(ipcp, opt->type);
! 876: break;
! 877: }
! 878: }
! 879: break;
! 880:
! 881: default:
! 882: assert(0);
! 883: }
! 884: }
! 885: }
! 886:
! 887: /*
! 888: * IpcpInput()
! 889: *
! 890: * Deal with an incoming IPCP packet
! 891: */
! 892:
! 893: void
! 894: IpcpInput(Bund b, Mbuf bp)
! 895: {
! 896: FsmInput(&b->ipcp.fsm, bp);
! 897: }
! 898:
! 899: #ifdef USE_NG_VJC
! 900: static int
! 901: IpcpNgInitVJ(Bund b)
! 902: {
! 903: struct ngm_mkpeer mp;
! 904: struct ngm_connect cn;
! 905: char path[NG_PATHSIZ];
! 906: struct ngm_name nm;
! 907:
! 908: /* Add a VJ compression node */
! 909: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 910: strcpy(mp.type, NG_VJC_NODE_TYPE);
! 911: strcpy(mp.ourhook, NG_PPP_HOOK_VJC_IP);
! 912: strcpy(mp.peerhook, NG_VJC_HOOK_IP);
! 913: if (NgSendMsg(gLinksCsock, path,
! 914: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 915: Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
! 916: b->name, NG_VJC_NODE_TYPE, path, mp.ourhook);
! 917: goto fail;
! 918: }
! 919:
! 920: /* Give it a name */
! 921: strlcat(path, NG_PPP_HOOK_VJC_IP, sizeof(path));
! 922: snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-vjc", gPid, b->name);
! 923: if (NgSendMsg(gLinksCsock, path,
! 924: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 925: Perror("[%s] can't name %s node", b->name, NG_VJC_NODE_TYPE);
! 926: goto fail;
! 927: }
! 928:
! 929: /* Connect the other three hooks between the ppp and vjc nodes */
! 930: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 931: strcpy(cn.path, NG_PPP_HOOK_VJC_IP);
! 932: strcpy(cn.ourhook, NG_PPP_HOOK_VJC_COMP);
! 933: strcpy(cn.peerhook, NG_VJC_HOOK_VJCOMP);
! 934: if (NgSendMsg(gLinksCsock, path,
! 935: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 936: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 937: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 938: goto fail;
! 939: }
! 940: strcpy(cn.ourhook, NG_PPP_HOOK_VJC_UNCOMP);
! 941: strcpy(cn.peerhook, NG_VJC_HOOK_VJUNCOMP);
! 942: if (NgSendMsg(gLinksCsock, path,
! 943: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 944: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 945: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 946: goto fail;
! 947: }
! 948: strcpy(cn.ourhook, NG_PPP_HOOK_VJC_VJIP);
! 949: strcpy(cn.peerhook, NG_VJC_HOOK_VJIP);
! 950: if (NgSendMsg(gLinksCsock, path,
! 951: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 952: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 953: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 954: goto fail;
! 955: }
! 956:
! 957: return 0;
! 958: fail:
! 959: return -1;
! 960: }
! 961:
! 962: static void
! 963: IpcpNgShutdownVJ(Bund b)
! 964: {
! 965: char path[NG_PATHSIZ];
! 966:
! 967: snprintf(path, sizeof(path), "[%x]:%s", b->nodeID, NG_PPP_HOOK_VJC_IP);
! 968: NgFuncShutdownNode(gLinksCsock, b->name, path);
! 969: }
! 970: #endif /* USE_NG_VJC */
! 971:
! 972: /*
! 973: * IpcpSetCommand()
! 974: */
! 975:
! 976: static int
! 977: IpcpSetCommand(Context ctx, int ac, char *av[], void *arg)
! 978: {
! 979: IpcpState const ipcp = &ctx->bund->ipcp;
! 980: struct in_addr *ips;
! 981:
! 982: if (ac == 0)
! 983: return(-1);
! 984: switch ((intptr_t)arg) {
! 985: case SET_RANGES:
! 986: {
! 987: struct u_range self_new_allow;
! 988: struct u_range peer_new_allow;
! 989: int pos = 0, self_new_pool = -1, peer_new_pool = -1;
! 990:
! 991: /* Parse args */
! 992: if (ac < 2)
! 993: return (-1);
! 994: if (strcmp(av[pos], "ippool") == 0) {
! 995: self_new_pool = pos+1;
! 996: pos+=2;
! 997: } else {
! 998: if (!ParseRange(av[pos], &self_new_allow, ALLOW_IPV4))
! 999: return(-1);
! 1000: pos++;
! 1001: }
! 1002: if (pos >= ac)
! 1003: return (-1);
! 1004: if (strcmp(av[pos], "ippool") == 0) {
! 1005: if ((pos + 1) >= ac)
! 1006: return (-1);
! 1007: peer_new_pool = pos+1;
! 1008: pos+=2;
! 1009: } else {
! 1010: if (!ParseRange(av[pos], &peer_new_allow, ALLOW_IPV4))
! 1011: return(-1);
! 1012: pos++;
! 1013: }
! 1014: if (pos != ac)
! 1015: return (-1);
! 1016:
! 1017: if (self_new_pool >= 0)
! 1018: strlcpy(ipcp->conf.self_ippool, av[self_new_pool], sizeof(ipcp->conf.self_ippool));
! 1019: else
! 1020: ipcp->conf.self_ippool[0] = 0;
! 1021: if (peer_new_pool >= 0)
! 1022: strlcpy(ipcp->conf.ippool, av[peer_new_pool], sizeof(ipcp->conf.ippool));
! 1023: else
! 1024: ipcp->conf.ippool[0] = 0;
! 1025: ipcp->conf.self_allow = self_new_allow;
! 1026: ipcp->conf.peer_allow = peer_new_allow;
! 1027:
! 1028: }
! 1029: break;
! 1030:
! 1031: case SET_DNS:
! 1032: ips = ipcp->conf.peer_dns;
! 1033: goto getPrimSec;
! 1034: break;
! 1035: case SET_NBNS:
! 1036: ips = ipcp->conf.peer_nbns;
! 1037: getPrimSec:
! 1038: if (!inet_aton(av[0], &ips[0]))
! 1039: Error("invalid IP address: \'%s\'", av[0]);
! 1040: ips[1].s_addr = 0;
! 1041: if (ac > 1 && !inet_aton(av[1], &ips[1]))
! 1042: Error("invalid IP address: \'%s\'", av[1]);
! 1043: break;
! 1044:
! 1045: case SET_ACCEPT:
! 1046: AcceptCommand(ac, av, &ipcp->conf.options, gConfList);
! 1047: break;
! 1048:
! 1049: case SET_DENY:
! 1050: DenyCommand(ac, av, &ipcp->conf.options, gConfList);
! 1051: break;
! 1052:
! 1053: case SET_ENABLE:
! 1054: EnableCommand(ac, av, &ipcp->conf.options, gConfList);
! 1055: break;
! 1056:
! 1057: case SET_DISABLE:
! 1058: DisableCommand(ac, av, &ipcp->conf.options, gConfList);
! 1059: break;
! 1060:
! 1061: case SET_YES:
! 1062: YesCommand(ac, av, &ipcp->conf.options, gConfList);
! 1063: break;
! 1064:
! 1065: case SET_NO:
! 1066: NoCommand(ac, av, &ipcp->conf.options, gConfList);
! 1067: break;
! 1068:
! 1069: default:
! 1070: assert(0);
! 1071: }
! 1072: return(0);
! 1073: }
! 1074:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>