static void ipv6cp_ValidateInterfaceID(struct ipv6cp *ipv6cp, u_char *ifid, struct fsm_decode *dec) { struct fsm_opt opt; u_char zero[IPV6CP_IFIDLEN]; memset(zero, 0, IPV6CP_IFIDLEN); if (memcmp(ifid, zero, IPV6CP_IFIDLEN) != 0 && memcmp(ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) != 0) memcpy(ipv6cp->his_ifid, ifid, IPV6CP_IFIDLEN); opt.hdr.id = TY_TOKEN; opt.hdr.len = IPV6CP_IFIDLEN + 2; memcpy(opt.data, &ipv6cp->his_ifid, IPV6CP_IFIDLEN); if (memcmp(ifid, ipv6cp->his_ifid, IPV6CP_IFIDLEN) == 0) fsm_ack(dec, &opt); else fsm_nak(dec, &opt); }
static void CcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, struct fsm_decode *dec) { /* Deal with incoming data */ struct ccp *ccp = fsm2ccp(fp); int f; const char *disp; struct fsm_opt *opt; if (mode_type == MODE_REQ) ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ while (end >= cp + sizeof(opt->hdr)) { if ((opt = fsm_readopt(&cp)) == NULL) break; for (f = NALGORITHMS-1; f > -1; f--) if (algorithm[f]->id == opt->hdr.id) break; disp = f == -1 ? "" : (*algorithm[f]->Disp)(opt); if (disp == NULL) disp = ""; log_Printf(LogCCP, " %s[%d] %s\n", protoname(opt->hdr.id), opt->hdr.len, disp); if (f == -1) { /* Don't understand that :-( */ if (mode_type == MODE_REQ) { ccp->my_reject |= (1 << opt->hdr.id); fsm_rej(dec, opt); } } else { struct ccp_opt *o; switch (mode_type) { case MODE_REQ: if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && (*algorithm[f]->Usable)(fp) && ccp->in.algorithm == -1) { memcpy(&ccp->in.opt, opt, opt->hdr.len); switch ((*algorithm[f]->i.Set)(fp->bundle, &ccp->in.opt, &ccp->cfg)) { case MODE_REJ: fsm_rej(dec, &ccp->in.opt); break; case MODE_NAK: fsm_nak(dec, &ccp->in.opt); break; case MODE_ACK: fsm_ack(dec, &ccp->in.opt); ccp->his_proto = opt->hdr.id; ccp->in.algorithm = (int)f; /* This one'll do :-) */ break; } } else { fsm_rej(dec, opt); } break; case MODE_NAK: for (o = ccp->out.opt; o != NULL; o = o->next) if (o->val.hdr.id == opt->hdr.id) break; if (o == NULL) log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent" " option\n", fp->link->name); else { memcpy(&o->val, opt, opt->hdr.len); if ((*algorithm[f]->o.Set)(fp->bundle, &o->val, &ccp->cfg) == MODE_ACK) ccp->my_proto = algorithm[f]->id; else { ccp->his_reject |= (1 << opt->hdr.id); ccp->my_proto = -1; if (algorithm[f]->Required(fp)) { log_Printf(LogWARN, "%s: Cannot understand peers (required)" " %s negotiation\n", fp->link->name, protoname(algorithm[f]->id)); fsm_Close(&fp->link->lcp.fsm); } } } break; case MODE_REJ: ccp->his_reject |= (1 << opt->hdr.id); ccp->my_proto = -1; if (algorithm[f]->Required(fp)) { log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n", fp->link->name, protoname(algorithm[f]->id)); fsm_Close(&fp->link->lcp.fsm); } break; } } } if (mode_type != MODE_NOP) { fsm_opt_normalise(dec); if (dec->rejend != dec->rej || dec->nakend != dec->nak) { if (ccp->in.state == NULL) { ccp->his_proto = -1; ccp->in.algorithm = -1; } } } }