static void Ipv6cpDecodeConfig(Fsm fp, FsmOption list, int num, int mode) { Bund b = (Bund) fp->arg; Ipv6cpState const ipv6cp = &b->ipv6cp; int k; /* Decode each config option */ for (k = 0; k < num; k++) { FsmOption const opt = &list[k]; FsmOptInfo const oi = FsmFindOptInfo(gIpv6cpConfOpts, opt->type); if (!oi) { Log(LG_IPV6CP, ("[%s] UNKNOWN[%d] len=%d", b->name, opt->type, opt->len)); if (mode == MODE_REQ) FsmRej(fp, opt); continue; } if (!oi->supported) { Log(LG_IPV6CP, ("[%s] %s", b->name, oi->name)); if (mode == MODE_REQ) { Log(LG_IPV6CP, ("[%s] Not supported", b->name)); FsmRej(fp, opt); } continue; } if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) { Log(LG_IPV6CP, ("[%s] %s", b->name, oi->name)); if (mode == MODE_REQ) { Log(LG_IPV6CP, ("[%s] bogus len=%d min=%d max=%d", b->name, opt->len, oi->minLen + 2, oi->maxLen + 2)); FsmRej(fp, opt); } continue; } switch (opt->type) { case TY_INTIDENT: { Log(LG_IPV6CP2, ("[%s] %s %02x%02x:%02x%02x:%02x%02x:%02x%02x", b->name, oi->name, opt->data[0], opt->data[1], opt->data[2], opt->data[3], opt->data[4], opt->data[5], opt->data[6], opt->data[7])); switch (mode) { case MODE_REQ: if ((((u_int32_t *)opt->data)[0] == 0) && (((u_int32_t *)opt->data)[1] == 0)) { Log(LG_IPV6CP2, ("[%s] Empty INTIDENT, propose our.", b->name)); CreateInterfaceID(ipv6cp->hisintid, 1); memcpy(opt->data, ipv6cp->hisintid, 8); FsmNak(fp, opt); } else if (bcmp(opt->data, ipv6cp->myintid, 8) == 0) { Log(LG_IPV6CP2, ("[%s] Duplicate INTIDENT, generate and propose other.", b->name)); CreateInterfaceID(ipv6cp->hisintid, 1); memcpy(opt->data, ipv6cp->hisintid, 8); FsmNak(fp, opt); } else { Log(LG_IPV6CP2, ("[%s] It's OK.", b->name)); memcpy(ipv6cp->hisintid, opt->data, 8); FsmAck(fp, opt); } break; case MODE_NAK: Log(LG_IPV6CP2, ("[%s] I agree to get this to myself.", b->name)); memcpy(ipv6cp->myintid, opt->data, 8); break; case MODE_REJ: IPV6CP_PEER_REJ(ipv6cp, opt->type); break; } } break; default: assert(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); } } }