void in_addrtou_range(const struct in_addr *src, u_char width, struct u_range *dst) { u_rangeclear(dst); in_addrtou_addr(src, &dst->addr); dst->width = width; }
static void IpcpUnConfigure(Fsm fp) { Bund b = (Bund)fp->arg; IpcpState const ipcp = &b->ipcp; if (ipcp->self_ippool_used) { struct u_addr ip; in_addrtou_addr(&ipcp->want_addr, &ip); IPPoolFree(ipcp->conf.self_ippool, &ip); ipcp->self_ippool_used = 0; } if (b->params.ippool_used) { struct u_addr ip; in_addrtou_addr(&ipcp->peer_addr, &ip); IPPoolFree(b->params.ippool, &ip); b->params.ippool_used = 0; } else if (ipcp->ippool_used) { struct u_addr ip; in_addrtou_addr(&ipcp->peer_addr, &ip); IPPoolFree(ipcp->conf.ippool, &ip); ipcp->ippool_used = 0; } }
static void IpcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode) { Bund b = (Bund)fp->arg; IpcpState const ipcp = &b->ipcp; struct in_addr *wantip, *peerip; int k; /* Decode each config option */ for (k = 0; k < num; k++) { FsmOption const opt = &list[k]; FsmOptInfo const oi = FsmFindOptInfo(gIpcpConfOpts, opt->type); if (!oi) { Log(LG_IPCP, ("[%s] UNKNOWN[%d] len=%d", b->name, opt->type, opt->len)); if (mode == MODE_REQ) FsmRej(fp, opt); continue; } if (!oi->supported) { Log(LG_IPCP, ("[%s] %s", b->name, oi->name)); if (mode == MODE_REQ) { Log(LG_IPCP, ("[%s] Not supported", b->name)); FsmRej(fp, opt); } continue; } if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) { Log(LG_IPCP, ("[%s] %s", b->name, oi->name)); if (mode == MODE_REQ) { Log(LG_IPCP, ("[%s] bogus len=%d", b->name, opt->len)); FsmRej(fp, opt); } continue; } switch (opt->type) { case TY_IPADDR: { struct in_addr ip; struct u_addr tmp; memcpy(&ip, opt->data, 4); in_addrtou_addr(&ip, &tmp); Log(LG_IPCP, ("[%s] %s %s", b->name, oi->name, inet_ntoa(ip))); switch (mode) { case MODE_REQ: if (!IpAddrInRange(&ipcp->peer_allow, &tmp) || !ip.s_addr) { if (ipcp->peer_addr.s_addr == 0) Log(LG_IPCP, ("[%s] no IP address available for peer!", b->name)); if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) { Log(LG_IPCP, ("[%s] pretending that %s is OK, will ignore", b->name, inet_ntoa(ip))); ipcp->peer_addr = ip; FsmAck(fp, opt); break; } memcpy(opt->data, &ipcp->peer_addr, 4); Log(LG_IPCP, ("[%s] NAKing with %s", b->name, inet_ntoa(ipcp->peer_addr))); FsmNak(fp, opt); break; } Log(LG_IPCP, ("[%s] %s is OK", b->name, inet_ntoa(ip))); ipcp->peer_addr = ip; FsmAck(fp, opt); break; case MODE_NAK: { if (IpAddrInRange(&ipcp->self_allow, &tmp)) { Log(LG_IPCP, ("[%s] %s is OK", b->name, inet_ntoa(ip))); ipcp->want_addr = ip; } else if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) { Log(LG_IPCP, ("[%s] pretending that %s is OK, will ignore", b->name, inet_ntoa(ip))); ipcp->want_addr = ip; } else Log(LG_IPCP, ("[%s] %s is unacceptable", b->name, inet_ntoa(ip))); } break; case MODE_REJ: IPCP_PEER_REJ(ipcp, opt->type); if (ipcp->want_addr.s_addr == 0) Log(LG_IPCP, ("[%s] Problem: I need an IP address!", b->name)); break; } } break; #ifdef USE_NG_VJC case TY_COMPPROTO: { struct ipcpvjcomp vj; memcpy(&vj, opt->data, sizeof(vj)); Log(LG_IPCP, ("[%s] %s %s, %d comp. channels, %s comp-cid", b->name, oi->name, ProtoName(ntohs(vj.proto)), vj.maxchan + 1, vj.compcid ? "allow" : "no")); switch (mode) { case MODE_REQ: if (!Acceptable(&ipcp->conf.options, IPCP_CONF_VJCOMP) && !b->params.vjc_enable) { FsmRej(fp, opt); break; } if (ntohs(vj.proto) == PROTO_VJCOMP && vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) { ipcp->peer_comp = vj; FsmAck(fp, opt); break; } vj.proto = htons(PROTO_VJCOMP); vj.maxchan = IPCP_VJCOMP_MAX_MAXCHAN; vj.compcid = 0; memcpy(opt->data, &vj, sizeof(vj)); FsmNak(fp, opt); break; case MODE_NAK: if (ntohs(vj.proto) != PROTO_VJCOMP) { Log(LG_IPCP, ("[%s] Can't accept proto 0x%04x", b->name, (u_short) ntohs(vj.proto))); break; } if (vj.maxchan != ipcp->want_comp.maxchan) { if (vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) { Log(LG_IPCP, ("[%s] Adjusting # compression channels", b->name)); ipcp->want_comp.maxchan = vj.maxchan; } else { Log(LG_IPCP, ("[%s] Can't handle %d maxchan", b->name, vj.maxchan)); } } if (vj.compcid) { Log(LG_IPCP, ("[%s] Can't accept comp-cid", b->name)); break; } break; case MODE_REJ: IPCP_PEER_REJ(ipcp, opt->type); ipcp->want_comp.proto = 0; break; } } break; #endif /* USE_NG_VJC */ case TY_PRIMARYDNS: if (b->params.peer_dns[0].s_addr != 0) peerip = &b->params.peer_dns[0]; else peerip = &ipcp->conf.peer_dns[0]; wantip = &ipcp->want_dns[0]; goto doDnsNbns; case TY_PRIMARYNBNS: if (b->params.peer_nbns[0].s_addr != 0) peerip = &b->params.peer_nbns[0]; else peerip = &ipcp->conf.peer_nbns[0]; wantip = &ipcp->want_nbns[0]; goto doDnsNbns; case TY_SECONDARYDNS: if (b->params.peer_dns[1].s_addr != 0) peerip = &b->params.peer_dns[1]; else peerip = &ipcp->conf.peer_dns[1]; wantip = &ipcp->want_dns[1]; goto doDnsNbns; case TY_SECONDARYNBNS: if (b->params.peer_nbns[1].s_addr != 0) peerip = &b->params.peer_nbns[1]; else peerip = &ipcp->conf.peer_nbns[1]; wantip = &ipcp->want_nbns[1]; doDnsNbns: { struct in_addr hisip; memcpy(&hisip, opt->data, 4); Log(LG_IPCP, ("[%s] %s %s", b->name, oi->name, inet_ntoa(hisip))); switch (mode) { case MODE_REQ: if (hisip.s_addr == 0) { /* he's asking for one */ if (peerip->s_addr == 0) { /* we don't got one */ FsmRej(fp, opt); break; } Log(LG_IPCP, ("[%s] NAKing with %s", b->name, inet_ntoa(*peerip))); memcpy(opt->data, peerip, sizeof(*peerip)); FsmNak(fp, opt); /* we got one for him */ break; } FsmAck(fp, opt); /* he knows what he wants */ break; case MODE_NAK: /* we asked for his server, he's telling us */ *wantip = hisip; break; case MODE_REJ: /* we asked for his server, he's ignorant */ IPCP_PEER_REJ(ipcp, opt->type); break; } } break; default: assert(0); } } }
static void IpcpLayerUp(Fsm fp) { Bund b = (Bund)fp->arg; IpcpState const ipcp = &b->ipcp; char ipbuf[20]; #ifdef USE_NG_VJC char path[NG_PATHSIZ]; struct ngm_vjc_config vjc; #endif struct u_addr tmp; /* Determine actual address we'll use for ourselves */ in_addrtou_addr(&ipcp->want_addr, &tmp); if (!IpAddrInRange(&ipcp->self_allow, &tmp)) { Log(LG_IPCP, ("[%s] Note: ignoring negotiated %s IP %s,", b->name, "self", inet_ntoa(ipcp->want_addr))); u_addrtoin_addr(&ipcp->self_allow.addr, &ipcp->want_addr); Log(LG_IPCP, ("[%s] using %s instead.", b->name, inet_ntoa(ipcp->want_addr))); } /* Determine actual address we'll use for peer */ in_addrtou_addr(&ipcp->peer_addr, &tmp); if (!IpAddrInRange(&ipcp->peer_allow, &tmp) && !u_addrempty(&ipcp->peer_allow.addr)) { Log(LG_IPCP, ("[%s] Note: ignoring negotiated %s IP %s,", b->name, "peer", inet_ntoa(ipcp->peer_addr))); u_addrtoin_addr(&ipcp->peer_allow.addr, &ipcp->peer_addr); Log(LG_IPCP, ("[%s] using %s instead.", b->name, inet_ntoa(ipcp->peer_addr))); } /* Report */ strlcpy(ipbuf, inet_ntoa(ipcp->peer_addr), sizeof(ipbuf)); Log(LG_IPCP, ("[%s] %s -> %s", b->name, inet_ntoa(ipcp->want_addr), ipbuf)); #ifdef USE_NG_VJC memset(&vjc, 0, sizeof(vjc)); if (ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP || ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP) { IpcpNgInitVJ(b); /* Configure VJ compression node */ vjc.enableComp = ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP; vjc.enableDecomp = ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP; vjc.maxChannel = ipcp->peer_comp.maxchan; vjc.compressCID = ipcp->peer_comp.compcid; snprintf(path, sizeof(path), "[%x]:%s", b->nodeID, NG_PPP_HOOK_VJC_IP); if (NgSendMsg(gLinksCsock, path, NGM_VJC_COOKIE, NGM_VJC_SET_CONFIG, &vjc, sizeof(vjc)) < 0) { Perror("[%s] can't config %s node", b->name, NG_VJC_NODE_TYPE); } } #endif /* USE_NG_VJC */ /* Enable IP packets in the PPP node */ b->pppConfig.bund.enableIP = 1; #ifdef USE_NG_VJC b->pppConfig.bund.enableVJCompression = vjc.enableComp; b->pppConfig.bund.enableVJDecompression = vjc.enableDecomp; #endif NgFuncSetConfig(b); BundNcpsJoin(b, NCP_IPCP); }