ipcp.c revision 21488
16059Samurai/*
26059Samurai *	PPP IP Control Protocol (IPCP) Module
36059Samurai *
46059Samurai *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
56059Samurai *
66059Samurai *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
76059Samurai *
86059Samurai * Redistribution and use in source and binary forms are permitted
96059Samurai * provided that the above copyright notice and this paragraph are
106059Samurai * duplicated in all such forms and that any documentation,
116059Samurai * advertising materials, and other materials related to such
126059Samurai * distribution and use acknowledge that the software was developed
136059Samurai * by the Internet Initiative Japan, Inc.  The name of the
146059Samurai * IIJ may not be used to endorse or promote products derived
156059Samurai * from this software without specific prior written permission.
166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
196059Samurai *
2021488Simp * $Id: ipcp.c,v 1.10 1996/12/12 14:39:44 jkh Exp $
218857Srgrimes *
226059Samurai *	TODO:
236059Samurai *		o More RFC1772 backwoard compatibility
246059Samurai */
256059Samurai#include "fsm.h"
266059Samurai#include "lcpproto.h"
276059Samurai#include "lcp.h"
286059Samurai#include "ipcp.h"
296059Samurai#include <netdb.h>
306059Samurai#include <netinet/in_systm.h>
316059Samurai#include <netinet/ip.h>
326059Samurai#include <arpa/inet.h>
336059Samurai#include <sys/socket.h>
346059Samurai#include "slcompress.h"
356059Samurai#include "os.h"
366059Samurai#include "phase.h"
376059Samurai#include "vars.h"
3820365Sjkh#include "alias.h"
396059Samurai
406059Samuraiextern void PutConfValue();
416059Samuraiextern void Prompt();
426059Samuraiextern struct in_addr ifnetmask;
436059Samurai
446059Samuraistruct ipcpstate IpcpInfo;
459440Samuraistruct in_range DefMyAddress, DefHisAddress, DefTriggerAddress;
466059Samurai
4718752Sjkh#ifdef MSEXT
4818752Sjkhstruct in_addr ns_entries[2], nbns_entries[2];
4918752Sjkh#endif /* MSEXT */
5018752Sjkh
516735Samuraistatic void IpcpSendConfigReq __P((struct fsm *));
526735Samuraistatic void IpcpSendTerminateAck __P((struct fsm *));
536735Samuraistatic void IpcpSendTerminateReq __P((struct fsm *));
546735Samuraistatic void IpcpDecodeConfig __P((u_char *, int, int));
556735Samuraistatic void IpcpLayerStart __P((struct fsm *));
566735Samuraistatic void IpcpLayerFinish __P((struct fsm *));
576735Samuraistatic void IpcpLayerUp __P((struct fsm *));
586735Samuraistatic void IpcpLayerDown __P((struct fsm *));
596735Samuraistatic void IpcpInitRestartCounter __P((struct fsm *));
606059Samurai
617001Samuraistruct pppTimer IpcpReportTimer;
626059Samurai
636059Samuraistatic int lastInOctets, lastOutOctets;
646059Samurai
656059Samurai#define	REJECTED(p, x)	(p->his_reject & (1<<x))
666059Samurai
676059Samuraistruct fsm IpcpFsm = {
686059Samurai  "IPCP",
696059Samurai  PROTO_IPCP,
706059Samurai  IPCP_MAXCODE,
716059Samurai  OPEN_ACTIVE,
726059Samurai  ST_INITIAL,
736059Samurai  0, 0, 0,
746059Samurai
756059Samurai  0,
766059Samurai  { 0, 0, 0, NULL, NULL, NULL },
776059Samurai
786059Samurai  IpcpLayerUp,
796059Samurai  IpcpLayerDown,
806059Samurai  IpcpLayerStart,
816059Samurai  IpcpLayerFinish,
826059Samurai  IpcpInitRestartCounter,
836059Samurai  IpcpSendConfigReq,
846059Samurai  IpcpSendTerminateReq,
856059Samurai  IpcpSendTerminateAck,
866059Samurai  IpcpDecodeConfig,
876059Samurai};
886059Samurai
896059Samuraistatic char *cftypes[] = {
906059Samurai  "???", "IPADDRS", "COMPPROTO", "IPADDR",
916059Samurai};
926059Samurai
936059Samurai/*
946059Samurai * Function called every second. Updates connection period and idle period,
956059Samurai * also update LQR information.
966059Samurai */
976059Samuraistatic void
986059SamuraiIpcpReportFunc()
996059Samurai{
1006059Samurai  ipConnectSecs++;
1016059Samurai  if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets)
1026059Samurai    ipIdleSecs++;
1036059Samurai  lastInOctets = ipInOctets;
1046059Samurai  lastOutOctets = ipOutOctets;
1056059Samurai  StopTimer(&IpcpReportTimer);
1066059Samurai  IpcpReportTimer.state = TIMER_STOPPED;
1076059Samurai  StartTimer(&IpcpReportTimer);
1086059Samurai}
1096059Samurai
1106059Samuraistatic void
1116059SamuraiIpcpStartReport()
1126059Samurai{
1136059Samurai  ipIdleSecs = ipConnectSecs = 0;
1146059Samurai  StopTimer(&IpcpReportTimer);
1156059Samurai  IpcpReportTimer.state = TIMER_STOPPED;
1166059Samurai  IpcpReportTimer.load = SECTICKS;
1176059Samurai  IpcpReportTimer.func = IpcpReportFunc;
1186059Samurai  StartTimer(&IpcpReportTimer);
1196059Samurai}
1206059Samurai
1216059Samuraivoid
1226059SamuraiReportIpcpStatus()
1236059Samurai{
1246059Samurai  struct ipcpstate *icp = &IpcpInfo;
1256059Samurai  struct fsm *fp = &IpcpFsm;
1266059Samurai
1276059Samurai  printf("%s [%s]\n", fp->name, StateNames[fp->state]);
12813389Sphk  printf(" his side: %s, %lx\n",
1296059Samurai     inet_ntoa(icp->his_ipaddr), icp->his_compproto);
13013389Sphk  printf(" my  side: %s, %lx\n",
1316059Samurai     inet_ntoa(icp->want_ipaddr), icp->want_compproto);
1326059Samurai  printf("connected: %d secs, idle: %d secs\n\n", ipConnectSecs, ipIdleSecs);
1339440Samurai  printf("Defaults:\n");
1349440Samurai  printf(" My Address:  %s/%d\n",
1356059Samurai     inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
1369440Samurai  printf(" His Address: %s/%d\n",
1376059Samurai     inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
1389440Samurai  printf(" Negotiation: %s/%d\n",
1399440Samurai     inet_ntoa(DefTriggerAddress.ipaddr), DefTriggerAddress.width);
1406059Samurai}
1416059Samurai
1426059Samuraivoid
1436059SamuraiIpcpDefAddress()
1446059Samurai{
1456059Samurai  struct hostent *hp;
1466059Samurai  char name[200];
1476059Samurai
1486059Samurai  bzero(&DefMyAddress, sizeof(DefMyAddress));
1496059Samurai  bzero(&DefHisAddress, sizeof(DefHisAddress));
1509440Samurai  bzero(&DefTriggerAddress, sizeof(DefTriggerAddress));
1516059Samurai  if (gethostname(name, sizeof(name)) == 0) {
1526059Samurai      hp = gethostbyname(name);
1536059Samurai      if (hp && hp->h_addrtype == AF_INET) {
1546059Samurai	bcopy(hp->h_addr, (char *)&DefMyAddress.ipaddr.s_addr, hp->h_length);
1556059Samurai      }
1566059Samurai  }
1576059Samurai}
1586059Samurai
1596059Samuraivoid
1606059SamuraiIpcpInit()
1616059Samurai{
1626059Samurai  struct ipcpstate *icp = &IpcpInfo;
1636059Samurai
1646059Samurai  FsmInit(&IpcpFsm);
1656059Samurai  bzero(icp, sizeof(struct ipcpstate));
1666059Samurai  if ((mode & MODE_DEDICATED) && !dstsystem) {
1676059Samurai    icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
1686059Samurai  } else {
1696059Samurai    icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
1706059Samurai    icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
1716059Samurai  }
1729440Samurai
1739440Samurai  /*
1749440Samurai   * Some implementation of PPP are:
1759440Samurai   *  Starting a negotiaion by require sending *special* value as my address,
1769440Samurai   *  even though standard of PPP is defined full negotiation based.
1779440Samurai   *  (e.g. "0.0.0.0" or Not "0.0.0.0")
1789440Samurai   */
1799440Samurai  if ( icp->want_ipaddr.s_addr == 0 ) {
1809440Samurai    icp->want_ipaddr.s_addr = DefTriggerAddress.ipaddr.s_addr;
1819440Samurai  }
1829440Samurai
1836059Samurai  if (Enabled(ConfVjcomp))
1846059Samurai    icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8);
1856059Samurai  else
1866059Samurai    icp->want_compproto = 0;
1876059Samurai  icp->heis1172 = 0;
1886059Samurai  IpcpFsm.maxconfig = 10;
1896059Samurai}
1906059Samurai
1916059Samuraistatic void
1926059SamuraiIpcpInitRestartCounter(fp)
1936059Samuraistruct fsm *fp;
1946059Samurai{
1956735Samurai  fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
1966059Samurai  fp->restart = 5;
1976059Samurai}
1986059Samurai
1996059Samuraistatic void
2006059SamuraiIpcpSendConfigReq(fp)
2016059Samuraistruct fsm *fp;
2026059Samurai{
2036059Samurai  u_char *cp;
2046059Samurai  struct ipcpstate *icp = &IpcpInfo;
2056059Samurai
2066059Samurai  cp = ReqBuff;
20715738Sphk  LogPrintf(LOG_LCP_BIT, "%s: SendConfigReq\n", fp->name);
2086735Samurai  if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR))
2096735Samurai    PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr));
2106059Samurai  if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
2116059Samurai    if (icp->heis1172)
2126059Samurai      PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16);
2136059Samurai    else
2146059Samurai      PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
2156059Samurai  }
2166059Samurai  FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
2176059Samurai}
2186059Samurai
2196059Samuraistatic void
2206059SamuraiIpcpSendTerminateReq(fp)
2216059Samuraistruct fsm *fp;
2226059Samurai{
2236059Samurai  /* XXX: No code yet */
2246059Samurai}
2256059Samurai
2266059Samuraistatic void
2276059SamuraiIpcpSendTerminateAck(fp)
2286059Samuraistruct fsm *fp;
2296059Samurai{
23015738Sphk  LogPrintf(LOG_LCP_BIT, "  %s: SendTerminateAck\n", fp->name);
2316059Samurai  FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2326059Samurai}
2336059Samurai
2346059Samuraistatic void
2356059SamuraiIpcpLayerStart(fp)
2366059Samuraistruct fsm *fp;
2376059Samurai{
23815738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerStart.\n", fp->name);
2396059Samurai}
2406059Samurai
2416059Samuraistatic void
2426059SamuraiIpcpLayerFinish(fp)
2436059Samuraistruct fsm *fp;
2446059Samurai{
24515738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerFinish.\n", fp->name);
2466059Samurai  LcpClose();
2476059Samurai  NewPhase(PHASE_TERMINATE);
2486059Samurai}
2496059Samurai
2506059Samuraistatic void
2516059SamuraiIpcpLayerDown(fp)
2526059Samuraistruct fsm *fp;
2536059Samurai{
25415738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerDown.\n", fp->name);
2556059Samurai  StopTimer(&IpcpReportTimer);
2566059Samurai}
2576059Samurai
2586059Samurai/*
2596059Samurai *  Called when IPCP has reached to OPEN state
2606059Samurai */
2616059Samuraistatic void
2626059SamuraiIpcpLayerUp(fp)
2636059Samuraistruct fsm *fp;
2646059Samurai{
2656059Samurai  char tbuff[100];
2666059Samurai
2676059Samurai#ifdef VERBOSE
2686059Samurai  fprintf(stderr, "%s: LayerUp(%d).\r\n", fp->name, fp->state);
2696059Samurai#endif
2706059Samurai  Prompt(1);
27115738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerUp.\n", fp->name);
27221488Simp  snprintf(tbuff, sizeof(tbuff), "myaddr = %s ",
27321488Simp    inet_ntoa(IpcpInfo.want_ipaddr));
27415738Sphk  LogPrintf(LOG_LCP_BIT|LOG_LINK_BIT, " %s hisaddr = %s\n", tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
2756059Samurai  OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask);
2766059Samurai  OsLinkup();
2776059Samurai  IpcpStartReport();
2786059Samurai  StartIdleTimer();
27920365Sjkh  if (mode & MODE_ALIAS)
28020365Sjkh    SetAliasAddress(IpcpInfo.want_ipaddr);
2816059Samurai}
2826059Samurai
2836059Samuraivoid
2846059SamuraiIpcpUp()
2856059Samurai{
2866059Samurai  FsmUp(&IpcpFsm);
28715738Sphk  LogPrintf(LOG_LCP_BIT, "IPCP Up event!!\n");
2886059Samurai}
2896059Samurai
2906059Samuraivoid
2916059SamuraiIpcpOpen()
2926059Samurai{
2936059Samurai  FsmOpen(&IpcpFsm);
2946059Samurai}
2956059Samurai
2966059Samuraistatic int
2976059SamuraiAcceptableAddr(prange, ipaddr)
2986059Samuraistruct in_range *prange;
2996059Samuraistruct in_addr ipaddr;
3006059Samurai{
3016059Samurai#ifdef DEBUG
3026059Samurai  logprintf("requested = %x ", htonl(ipaddr.s_addr));
3036059Samurai  logprintf("range = %x", htonl(prange->ipaddr.s_addr));
3046059Samurai  logprintf("/%x\n", htonl(prange->mask.s_addr));
3056059Samurai  logprintf("%x, %x\n", htonl(prange->ipaddr.s_addr & prange->mask.s_addr),
3066059Samurai    htonl(ipaddr.s_addr & prange->mask.s_addr));
3076059Samurai#endif
3086059Samurai  return((prange->ipaddr.s_addr & prange->mask.s_addr) ==
3096059Samurai	(ipaddr.s_addr & prange->mask.s_addr));
3106059Samurai}
3116059Samurai
3126059Samuraistatic void
3136735SamuraiIpcpDecodeConfig(cp, plen, mode)
3146735Samuraiu_char *cp;
3156735Samuraiint plen;
3166059Samuraiint mode;
3176059Samurai{
3186735Samurai  int type, length;
3196059Samurai  u_long *lp, compproto;
3206059Samurai  struct compreq *pcomp;
32118752Sjkh  struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
3226059Samurai  char tbuff[100];
32321488Simp  char tbuff2[100];
3246059Samurai
3256059Samurai  ackp = AckBuff;
3266059Samurai  nakp = NakBuff;
3276059Samurai  rejp = RejBuff;
3286059Samurai
3296059Samurai  while (plen >= sizeof(struct fsmconfig)) {
3306059Samurai    if (plen < 0)
3316059Samurai      break;
3326059Samurai    type = *cp;
3336059Samurai    length = cp[1];
3346059Samurai    if (type <= TY_IPADDR)
33521488Simp      snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
3366059Samurai    else
33721488Simp      snprintf(tbuff, sizeof(tbuff), " ");
3386059Samurai
3396059Samurai    switch (type) {
3406059Samurai    case TY_IPADDR:		/* RFC1332 */
3416059Samurai      lp = (u_long *)(cp + 2);
3426059Samurai      ipaddr.s_addr = *lp;
34315738Sphk      LogPrintf(LOG_LCP_BIT, "%s %s\n", tbuff, inet_ntoa(ipaddr));
3446059Samurai
3456059Samurai      switch (mode) {
3466059Samurai      case MODE_REQ:
3476059Samurai	if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
3486059Samurai          /*
3496059Samurai           * If destination address is not acceptable, insist to use
3506059Samurai           * what we want to use.
3516059Samurai           */
3526059Samurai	  bcopy(cp, nakp, 2);
3536059Samurai          bcopy(&IpcpInfo.his_ipaddr.s_addr, nakp+2, length);
3546059Samurai          nakp += length;
3556059Samurai          break;
3568857Srgrimes
3576059Samurai	}
3586059Samurai	IpcpInfo.his_ipaddr = ipaddr;
3596059Samurai	bcopy(cp, ackp, length);
3606059Samurai	ackp += length;
3616059Samurai	break;
3626059Samurai      case MODE_NAK:
3636059Samurai	if (AcceptableAddr(&DefMyAddress, ipaddr)) {
3646059Samurai          /*
3656059Samurai           * Use address suggested by peer.
3666059Samurai           */
36721488Simp	  snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
36821488Simp	  LogPrintf(LOG_LCP_BIT, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
3696059Samurai	  IpcpInfo.want_ipaddr = ipaddr;
3706059Samurai	}
3716059Samurai	break;
3726059Samurai      case MODE_REJ:
3736059Samurai	IpcpInfo.his_reject |= (1 << type);
3746059Samurai	break;
3756059Samurai      }
3766059Samurai      break;
3776059Samurai    case TY_COMPPROTO:
3786059Samurai      lp = (u_long *)(cp + 2);
3796059Samurai      compproto = htonl(*lp);
38015738Sphk      LogPrintf(LOG_LCP_BIT, "%s %08x\n", tbuff, compproto);
3816059Samurai
3826059Samurai      switch (mode) {
3836059Samurai      case MODE_REQ:
3846059Samurai	if (!Acceptable(ConfVjcomp)) {
3856059Samurai	  bcopy(cp, rejp, length);
3866059Samurai	  rejp += length;
3876059Samurai	} else {
3886059Samurai	  pcomp = (struct compreq *)(cp + 2);
3896059Samurai	  switch (length) {
3906059Samurai	  case 4:	/* RFC1172 */
3916059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
3926059Samurai	      logprintf("** Peer is speaking RFC1172 compression protocol **\n");
3936059Samurai	      IpcpInfo.heis1172 = 1;
3946059Samurai	      IpcpInfo.his_compproto = compproto;
3956059Samurai	      bcopy(cp, ackp, length);
3966059Samurai	      ackp += length;
3976059Samurai	    } else {
3986059Samurai	      bcopy(cp, nakp, 2);
3996059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
4006059Samurai	      bcopy(&pcomp, nakp + 2, 2);
4016059Samurai	      nakp += length;
4026059Samurai	    }
4036059Samurai	    break;
4046059Samurai	  case 6: 	/* RFC1332 */
4056059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
4066059Samurai	        && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
4076059Samurai	      IpcpInfo.his_compproto = compproto;
4086059Samurai	      IpcpInfo.heis1172 = 0;
4096059Samurai	      bcopy(cp, ackp, length);
4106059Samurai	      ackp += length;
4116059Samurai	    } else {
4126059Samurai	      bcopy(cp, nakp, 2);
4136059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
4146059Samurai	      pcomp->slots = MAX_STATES - 1;
4156059Samurai	      pcomp->compcid = 0;
4166059Samurai	      bcopy(&pcomp, nakp + 2, sizeof(pcomp));
4176059Samurai	      nakp += length;
4186059Samurai	    }
4196059Samurai	    break;
4206059Samurai	  default:
4216059Samurai	    bcopy(cp, rejp, length);
4226059Samurai	    rejp += length;
4236059Samurai	    break;
4246059Samurai	  }
4256059Samurai	}
4266059Samurai	break;
4276059Samurai      case MODE_NAK:
42815738Sphk	LogPrintf(LOG_LCP_BIT, "%s changing compproto: %08x --> %08x\n",
4296059Samurai	  tbuff, IpcpInfo.want_compproto, compproto);
4306059Samurai	IpcpInfo.want_compproto = compproto;
4316059Samurai	break;
4326059Samurai      case MODE_REJ:
4336059Samurai	IpcpInfo.his_reject |= (1 << type);
4346059Samurai	break;
4356059Samurai      }
4366059Samurai      break;
4376059Samurai    case TY_IPADDRS:	/* RFC1172 */
4386059Samurai      lp = (u_long *)(cp + 2);
4396059Samurai      ipaddr.s_addr = *lp;
4406059Samurai      lp = (u_long *)(cp + 6);
4416059Samurai      dstipaddr.s_addr = *lp;
44215738Sphk      LogPrintf(LOG_LCP_BIT, "%s %s, ", tbuff, inet_ntoa(ipaddr));
44315738Sphk      LogPrintf(LOG_LCP_BIT, "%s\n", inet_ntoa(dstipaddr));
4446059Samurai
4456059Samurai      switch (mode) {
4466059Samurai      case MODE_REQ:
4476059Samurai	IpcpInfo.his_ipaddr = ipaddr;
4486059Samurai	IpcpInfo.want_ipaddr = dstipaddr;
4496059Samurai	bcopy(cp, ackp, length);
4506059Samurai	ackp += length;
4516059Samurai	break;
4526059Samurai      case MODE_NAK:
45315738Sphk	LogPrintf(LOG_LCP_BIT, "%s changing address: %s ",
4546059Samurai	  tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
45515738Sphk	LogPrintf(LOG_LCP_BIT, "--> %s\n", inet_ntoa(ipaddr));
4566059Samurai	IpcpInfo.want_ipaddr = ipaddr;
4576059Samurai	IpcpInfo.his_ipaddr = dstipaddr;
4586059Samurai	break;
4596059Samurai      case MODE_REJ:
4606059Samurai	IpcpInfo.his_reject |= (1 << type);
4616059Samurai	break;
4626059Samurai      }
4636059Samurai      break;
46418752Sjkh
46518752Sjkh /*
46618752Sjkh  * MS extensions for MS's PPP
46718752Sjkh  */
46818752Sjkh
46918752Sjkh#ifdef MSEXT
47018752Sjkh    case TY_PRIMARY_DNS:   /* MS PPP DNS negotiation hack */
47118752Sjkh    case TY_SECONDARY_DNS:
47218752Sjkh      if( !Enabled( ConfMSExt ) ) {
47318752Sjkh	LogPrintf( LOG_LCP, "MS NS req - rejected - msext disabled\n" );
47418752Sjkh	IpcpInfo.my_reject |= ( 1 << type );
47518752Sjkh	bcopy(cp, rejp, length);
47618752Sjkh	rejp += length;
47718752Sjkh	break;
47818752Sjkh      }
47918752Sjkh      switch( mode ){
48018752Sjkh      case MODE_REQ:
48118752Sjkh	lp = (u_long *)(cp + 2);
48218752Sjkh	dnsstuff.s_addr = *lp;
48318752Sjkh	ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS)?1:0)].s_addr;
48418752Sjkh	if( dnsstuff.s_addr != ms_info_req.s_addr )
48518752Sjkh	{
48618752Sjkh	  /*
48718752Sjkh	   So the client has got the DNS stuff wrong (first request)
48818752Sjkh	   so well tell 'em how it is
48918752Sjkh	  */
49018752Sjkh	  bcopy( cp, nakp, 2 );  /* copy first two (type/length) */
49118752Sjkh	  LogPrintf( LOG_LCP, "MS NS req %d:%s->%s - nak\n",
49218752Sjkh		type,
49318752Sjkh		inet_ntoa( dnsstuff ),
49418752Sjkh		inet_ntoa( ms_info_req ));
49518752Sjkh	  bcopy( &ms_info_req, nakp+2, length );
49618752Sjkh	  nakp += length;
49718752Sjkh	  break;
49818752Sjkh	}
49918752Sjkh	  /*
50018752Sjkh	   Otherwise they have it right (this time) so we send
50118752Sjkh	   a ack packet back confirming it... end of story
50218752Sjkh	  */
50318752Sjkh	LogPrintf( LOG_LCP, "MS NS req %d:%s ok - ack\n",
50418752Sjkh		type,
50518752Sjkh		inet_ntoa( ms_info_req ));
50618752Sjkh	bcopy( cp, ackp, length );
50718752Sjkh	ackp += length;
50818752Sjkh	break;
50918752Sjkh      case MODE_NAK: /* what does this mean?? */
51018752Sjkh	LogPrintf(LOG_LCP, "MS NS req %d - NAK??\n", type );
51118752Sjkh	break;
51218752Sjkh      case MODE_REJ: /* confused?? me to :) */
51318752Sjkh	LogPrintf(LOG_LCP, "MS NS req %d - REJ??\n", type );
51418752Sjkh	break;
51518752Sjkh      }
51618752Sjkh      break;
51718752Sjkh
51818752Sjkh    case TY_PRIMARY_NBNS:   /* MS PPP NetBIOS nameserver hack */
51918752Sjkh    case TY_SECONDARY_NBNS:
52018752Sjkh    if( !Enabled( ConfMSExt ) ) {
52118752Sjkh      LogPrintf( LOG_LCP, "MS NBNS req - rejected - msext disabled\n" );
52218752Sjkh      IpcpInfo.my_reject |= ( 1 << type );
52318752Sjkh      bcopy( cp, rejp, length );
52418752Sjkh      rejp += length;
52518752Sjkh      break;
52618752Sjkh    }
52718752Sjkh      switch( mode ){
52818752Sjkh      case MODE_REQ:
52918752Sjkh	lp = (u_long *)(cp + 2);
53018752Sjkh	dnsstuff.s_addr = *lp;
53118752Sjkh	ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS)?1:0)].s_addr;
53218752Sjkh	if( dnsstuff.s_addr != ms_info_req.s_addr )
53318752Sjkh	{
53418752Sjkh	  bcopy( cp, nakp, 2 );
53518752Sjkh	  bcopy( &ms_info_req.s_addr , nakp+2, length );
53618752Sjkh	  LogPrintf( LOG_LCP, "MS NBNS req %d:%s->%s - nak\n",
53718752Sjkh		type,
53818752Sjkh		inet_ntoa( dnsstuff ),
53918752Sjkh		inet_ntoa( ms_info_req ));
54018752Sjkh	  nakp += length;
54118752Sjkh	  break;
54218752Sjkh	}
54318752Sjkh	LogPrintf( LOG_LCP, "MS NBNS req %d:%s ok - ack\n",
54418752Sjkh		type,
54518752Sjkh		inet_ntoa( ms_info_req ));
54618752Sjkh	bcopy( cp, ackp, length );
54718752Sjkh	ackp += length;
54818752Sjkh	break;
54918752Sjkh      case MODE_NAK:
55018752Sjkh	LogPrintf( LOG_LCP, "MS NBNS req %d - NAK??\n", type );
55118752Sjkh	break;
55218752Sjkh      case MODE_REJ:
55318752Sjkh	LogPrintf( LOG_LCP, "MS NBNS req %d - REJ??\n", type );
55418752Sjkh	break;
55518752Sjkh      }
55618752Sjkh      break;
55718752Sjkh
55818752Sjkh#endif /* MSEXT */
55918752Sjkh
5606059Samurai    default:
5616059Samurai      IpcpInfo.my_reject |= (1 << type);
5626059Samurai      bcopy(cp, rejp, length);
5636059Samurai      rejp += length;
5646059Samurai      break;
5656059Samurai    }
5666059Samurai    plen -= length;
5676059Samurai    cp += length;
5686059Samurai  }
5696059Samurai}
5706059Samurai
5716059Samuraivoid
5726059SamuraiIpcpInput(struct mbuf *bp)
5736059Samurai{
5746059Samurai  FsmInput(&IpcpFsm, bp);
5756059Samurai}
576