ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); memcpy(dec->rejend, cp, length); dec->rejend += length; break; } have_ip = ipcp->ns.dns[type == TY_PRIMARY_DNS ? 0 : 1];  if (type == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&
ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); fsm_rej(dec, opt); break; } have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1];  if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&
IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,                 struct fsm_decode *dec){  /* Deal with incoming PROTO_IPCP */  struct ncpaddr ncpaddr;  struct ipcp *ipcp = fsm2ipcp(fp);  int type, length, gotdnsnak;  u_int32_t compproto;  struct compreq *pcomp;  struct in_addr ipaddr, dstipaddr, have_ip;  char tbuff[100], tbuff2[100];  gotdnsnak = 0;  while (plen >= sizeof(struct fsmconfig)) {    type = *cp;    length = cp[1];    if (length == 0) {      log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);      break;    }    snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length);    switch (type) {    case TY_IPADDR:		/* RFC1332 */      memcpy(&ipaddr.s_addr, cp + 2, 4);      log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));      switch (mode_type) {      case MODE_REQ:        ipcp->peer_req = 1;        ipcp_ValidateReq(ipcp, ipaddr, dec);	break;      case MODE_NAK:        if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) {	  /* Use address suggested by peer */	  snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,		   inet_ntoa(ipcp->my_ip));	  log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));	  ipcp->my_ip = ipaddr;          ncpaddr_setip4(&ncpaddr, ipcp->my_ip);          bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL);	} else {	  log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,                    "%s: Unacceptable address!\n", inet_ntoa(ipaddr));          fsm_Close(&ipcp->fsm);	}	break;      case MODE_REJ:	ipcp->peer_reject |= (1 << type);	break;      }      break;    case TY_COMPPROTO:      pcomp = (struct compreq *)(cp + 2);      compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) +                  pcomp->compcid;      log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));      switch (mode_type) {      case MODE_REQ:	if (!IsAccepted(ipcp->cfg.vj.neg)) {	  memcpy(dec->rejend, cp, length);	  dec->rejend += length;	} else {	  switch (length) {	  case 4:		/* RFC1172 */	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {	      log_Printf(LogWARN, "Peer is speaking RFC1172 compression "                         "protocol !\n");	      ipcp->heis1172 = 1;	      ipcp->peer_compproto = compproto;	      memcpy(dec->ackend, cp, length);	      dec->ackend += length;	    } else {	      memcpy(dec->nakend, cp, 2);	      pcomp->proto = htons(PROTO_VJCOMP);	      memcpy(dec->nakend+2, &pcomp, 2);	      dec->nakend += length;	    }	    break;	  case 6:		/* RFC1332 */	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {              if (pcomp->slots <= MAX_VJ_STATES                  && pcomp->slots >= MIN_VJ_STATES) {                /* Ok, we can do that */	        ipcp->peer_compproto = compproto;	        ipcp->heis1172 = 0;	        memcpy(dec->ackend, cp, length);	        dec->ackend += length;	      } else {                /* Get as close as we can to what he wants */	        ipcp->heis1172 = 0;	        memcpy(dec->nakend, cp, 2);	        pcomp->slots = pcomp->slots < MIN_VJ_STATES ?                               MIN_VJ_STATES : MAX_VJ_STATES;	        memcpy(dec->nakend+2, &pcomp, sizeof pcomp);	        dec->nakend += length;              }	    } else {              /* What we really want */	      memcpy(dec->nakend, cp, 2);	      pcomp->proto = htons(PROTO_VJCOMP);	      pcomp->slots = DEF_VJ_STATES;	      pcomp->compcid = 1;	      memcpy(dec->nakend+2, &pcomp, sizeof pcomp);	      dec->nakend += length;	    }	    break;	  default:	    memcpy(dec->rejend, cp, length);	    dec->rejend += length;	    break;	  }	}	break;      case MODE_NAK:	if (ntohs(pcomp->proto) == PROTO_VJCOMP) {          if (pcomp->slots > MAX_VJ_STATES)            pcomp->slots = MAX_VJ_STATES;          else if (pcomp->slots < MIN_VJ_STATES)            pcomp->slots = MIN_VJ_STATES;          compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) +                      pcomp->compcid;        } else          compproto = 0;	log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",		  tbuff, ipcp->my_compproto, compproto);        ipcp->my_compproto = compproto;	break;      case MODE_REJ:	ipcp->peer_reject |= (1 << type);	break;      }      break;    case TY_IPADDRS:		/* RFC1172 */      memcpy(&ipaddr.s_addr, cp + 2, 4);      memcpy(&dstipaddr.s_addr, cp + 6, 4);      snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));      log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));      switch (mode_type) {      case MODE_REQ:	memcpy(dec->rejend, cp, length);	dec->rejend += length;	break;      case MODE_NAK:      case MODE_REJ:	break;      }      break;    case TY_PRIMARY_DNS:	/* DNS negotiation (rfc1877) */    case TY_SECONDARY_DNS:      memcpy(&ipaddr.s_addr, cp + 2, 4);      log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));      switch (mode_type) {      case MODE_REQ:        if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {          ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));	  memcpy(dec->rejend, cp, length);	  dec->rejend += length;	  break;        }        have_ip = ipcp->ns.dns[type == TY_PRIMARY_DNS ? 0 : 1];        if (type == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&            ipaddr.s_addr == ipcp->ns.dns[1].s_addr) {          /* Swap 'em 'round */          ipcp->ns.dns[0] = ipcp->ns.dns[1];          ipcp->ns.dns[1] = have_ip;          have_ip = ipcp->ns.dns[0];        }	if (ipaddr.s_addr != have_ip.s_addr) {	  /*	   * The client has got the DNS stuff wrong (first request) so	   * we'll tell 'em how it is	   */	  memcpy(dec->nakend, cp, 2);	/* copy first two (type/length) */	  memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);	  dec->nakend += length;	} else {	  /*	   * Otherwise they have it right (this time) so we send a ack packet	   * back confirming it... end of story	   */	  memcpy(dec->ackend, cp, length);	  dec->ackend += length;        }	break;      case MODE_NAK:        if (IsEnabled(ipcp->cfg.ns.dns_neg)) {          gotdnsnak = 1;          memcpy(&ipcp->ns.dns[type == TY_PRIMARY_DNS ? 0 : 1].s_addr,                 cp + 2, 4);	}	break;      case MODE_REJ:		/* Can't do much, stop asking */        ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));	break;      }      break;    case TY_PRIMARY_NBNS:	/* M$ NetBIOS nameserver hack (rfc1877) */    case TY_SECONDARY_NBNS:      memcpy(&ipaddr.s_addr, cp + 2, 4);      log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));      switch (mode_type) {      case MODE_REQ:	have_ip.s_addr =          ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;        if (have_ip.s_addr == INADDR_ANY) {	  log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");          ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));	  memcpy(dec->rejend, cp, length);	  dec->rejend += length;	  break;        }	if (ipaddr.s_addr != have_ip.s_addr) {	  memcpy(dec->nakend, cp, 2);	  memcpy(dec->nakend+2, &have_ip.s_addr, length);	  dec->nakend += length;	} else {	  memcpy(dec->ackend, cp, length);	  dec->ackend += length;        }	break;      case MODE_NAK:	log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);	break;      case MODE_REJ:	log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);	break;      }      break;    default:      if (mode_type != MODE_NOP) {        ipcp->my_reject |= (1 << type);        memcpy(dec->rejend, cp, length);        dec->rejend += length;      }      break;    }    plen -= length;    cp += length;  }  if (gotdnsnak) {    if (ipcp->ns.writable) {      log_Printf(LogDEBUG, "Updating resolver\n");      if (!ipcp_WriteDNS(ipcp)) {        ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));        ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));      } else        bundle_AdjustDNS(fp->bundle);    } else {      log_Printf(LogDEBUG, "Not updating resolver (readonly)\n");      bundle_AdjustDNS(fp->bundle);    }  }  if (mode_type != MODE_NOP) {    if (mode_type == MODE_REQ && !ipcp->peer_req) {      if (dec->rejend == dec->rej && dec->nakend == dec->nak) {        /*         * Pretend the peer has requested an IP.         * 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_IPADDR REQ.  This stops us from repeatedly trying to tell         * the peer that we have to have an IP address on their end.         */        ipcp->peer_req = 1;      }      ipaddr.s_addr = INADDR_ANY;      ipcp_ValidateReq(ipcp, ipaddr, 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;  }}