while (plen >= sizeof(struct fsmconfig)) { type = *cp; length = cp[1];
while (end - cp >= sizeof(opt->hdr)) { if ((opt = fsm_readopt(&cp)) == NULL) break;
ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,                    struct fsm_decode *dec){  /* Deal with incoming PROTO_IPV6CP */  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);  int type, length, n;  char tbuff[100];  u_int32_t token;  while (plen >= sizeof(struct fsmconfig)) {    type = *cp;    length = cp[1];    if (length == 0) {      log_Printf(LogIPV6CP, "%s: IPV6CP size zero\n", fp->link->name);      break;    }    snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length);    switch (type) {    case TY_TOKEN:      memcpy(&token, cp + 2, 4);      log_Printf(LogIPV6CP, "%s 0x%08lx\n", tbuff, (unsigned long)token);      switch (mode_type) {      case MODE_REQ:        ipv6cp->peer_tokenreq = 1;        ipv6cp_ValidateToken(ipv6cp, token, dec);	break;      case MODE_NAK:        if (token == 0) {	  log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,                     "0x00000000: Unacceptable token!\n");          fsm_Close(&ipv6cp->fsm);        } else if (token == ipv6cp->peer_token)	  log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,                    "0x%08lx: Unacceptable token!\n", (unsigned long)token);        else if (token != ipv6cp->my_token) {          n = 100;          while (n && !ipcp_SetIPv6address(ipv6cp, token, ipv6cp->peer_token)) {            n--;            while (n && (token = GenerateToken()) == ipv6cp->peer_token)              n--;          }          if (n == 0) {	    log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,                       "0x00000000: Unacceptable token!\n");            fsm_Close(&ipv6cp->fsm);          } else {	    log_Printf(LogIPV6CP, "%s changing token: 0x%08lx --> 0x%08lx\n",                       tbuff, (unsigned long)ipv6cp->my_token,                       (unsigned long)token);            ipv6cp->my_token = token;            bundle_AdjustFilters(fp->bundle, &ipv6cp->myaddr, NULL);          }        }	break;      case MODE_REJ:	ipv6cp->his_reject |= (1 << type);	break;      }      break;    default:      if (mode_type != MODE_NOP) {        ipv6cp->my_reject |= (1 << type);        memcpy(dec->rejend, cp, length);        dec->rejend += length;      }      break;    }    plen -= length;    cp += length;  }  if (mode_type != MODE_NOP) {    if (mode_type == MODE_REQ && !ipv6cp->peer_tokenreq) {      if (dec->rejend == dec->rej && dec->nakend == dec->nak) {        /*         * Pretend the peer has requested a TOKEN.         * We do this to ensure that we only send one NAK if the only         * reason for the NAK is because the peer isn't sending a         * TY_TOKEN REQ.  This stops us from repeatedly trying to tell         * the peer that we have to have an IP address on their end.         */        ipv6cp->peer_tokenreq = 1;      }      ipv6cp_ValidateToken(ipv6cp, 0, dec);    }    if (dec->rejend != dec->rej) {      /* rejects are preferred */      dec->ackend = dec->ack;      dec->nakend = dec->nak;    } else if (dec->nakend != dec->nak)      /* then NAKs */      dec->ackend = dec->ack;  }}