ipcp.c revision 25630
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 *
2025630Sbrian * $Id: ipcp.c,v 1.13 1997/02/22 16:10:20 peter 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
12125630Sbrianint
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);
14025630Sbrian  return 0;
1416059Samurai}
1426059Samurai
1436059Samuraivoid
1446059SamuraiIpcpDefAddress()
1456059Samurai{
1466059Samurai  struct hostent *hp;
1476059Samurai  char name[200];
1486059Samurai
1496059Samurai  bzero(&DefMyAddress, sizeof(DefMyAddress));
1506059Samurai  bzero(&DefHisAddress, sizeof(DefHisAddress));
1519440Samurai  bzero(&DefTriggerAddress, sizeof(DefTriggerAddress));
1526059Samurai  if (gethostname(name, sizeof(name)) == 0) {
1536059Samurai      hp = gethostbyname(name);
1546059Samurai      if (hp && hp->h_addrtype == AF_INET) {
1556059Samurai	bcopy(hp->h_addr, (char *)&DefMyAddress.ipaddr.s_addr, hp->h_length);
1566059Samurai      }
1576059Samurai  }
1586059Samurai}
1596059Samurai
1606059Samuraivoid
1616059SamuraiIpcpInit()
1626059Samurai{
1636059Samurai  struct ipcpstate *icp = &IpcpInfo;
1646059Samurai
1656059Samurai  FsmInit(&IpcpFsm);
1666059Samurai  bzero(icp, sizeof(struct ipcpstate));
1676059Samurai  if ((mode & MODE_DEDICATED) && !dstsystem) {
1686059Samurai    icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
1696059Samurai  } else {
1706059Samurai    icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
1716059Samurai    icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
1726059Samurai  }
1739440Samurai
1749440Samurai  /*
1759440Samurai   * Some implementation of PPP are:
1769440Samurai   *  Starting a negotiaion by require sending *special* value as my address,
1779440Samurai   *  even though standard of PPP is defined full negotiation based.
1789440Samurai   *  (e.g. "0.0.0.0" or Not "0.0.0.0")
1799440Samurai   */
1809440Samurai  if ( icp->want_ipaddr.s_addr == 0 ) {
1819440Samurai    icp->want_ipaddr.s_addr = DefTriggerAddress.ipaddr.s_addr;
1829440Samurai  }
1839440Samurai
1846059Samurai  if (Enabled(ConfVjcomp))
1856059Samurai    icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8);
1866059Samurai  else
1876059Samurai    icp->want_compproto = 0;
1886059Samurai  icp->heis1172 = 0;
1896059Samurai  IpcpFsm.maxconfig = 10;
1906059Samurai}
1916059Samurai
1926059Samuraistatic void
1936059SamuraiIpcpInitRestartCounter(fp)
1946059Samuraistruct fsm *fp;
1956059Samurai{
1966735Samurai  fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
1976059Samurai  fp->restart = 5;
1986059Samurai}
1996059Samurai
2006059Samuraistatic void
2016059SamuraiIpcpSendConfigReq(fp)
2026059Samuraistruct fsm *fp;
2036059Samurai{
2046059Samurai  u_char *cp;
2056059Samurai  struct ipcpstate *icp = &IpcpInfo;
2066059Samurai
2076059Samurai  cp = ReqBuff;
20815738Sphk  LogPrintf(LOG_LCP_BIT, "%s: SendConfigReq\n", fp->name);
2096735Samurai  if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR))
2106735Samurai    PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr));
2116059Samurai  if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
2126059Samurai    if (icp->heis1172)
2136059Samurai      PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16);
2146059Samurai    else
2156059Samurai      PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
2166059Samurai  }
2176059Samurai  FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
2186059Samurai}
2196059Samurai
2206059Samuraistatic void
2216059SamuraiIpcpSendTerminateReq(fp)
2226059Samuraistruct fsm *fp;
2236059Samurai{
2246059Samurai  /* XXX: No code yet */
2256059Samurai}
2266059Samurai
2276059Samuraistatic void
2286059SamuraiIpcpSendTerminateAck(fp)
2296059Samuraistruct fsm *fp;
2306059Samurai{
23115738Sphk  LogPrintf(LOG_LCP_BIT, "  %s: SendTerminateAck\n", fp->name);
2326059Samurai  FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2336059Samurai}
2346059Samurai
2356059Samuraistatic void
2366059SamuraiIpcpLayerStart(fp)
2376059Samuraistruct fsm *fp;
2386059Samurai{
23915738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerStart.\n", fp->name);
2406059Samurai}
2416059Samurai
2426059Samuraistatic void
2436059SamuraiIpcpLayerFinish(fp)
2446059Samuraistruct fsm *fp;
2456059Samurai{
24615738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerFinish.\n", fp->name);
2476059Samurai  LcpClose();
2486059Samurai  NewPhase(PHASE_TERMINATE);
2496059Samurai}
2506059Samurai
2516059Samuraistatic void
2526059SamuraiIpcpLayerDown(fp)
2536059Samuraistruct fsm *fp;
2546059Samurai{
25515738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerDown.\n", fp->name);
2566059Samurai  StopTimer(&IpcpReportTimer);
2576059Samurai}
2586059Samurai
2596059Samurai/*
2606059Samurai *  Called when IPCP has reached to OPEN state
2616059Samurai */
2626059Samuraistatic void
2636059SamuraiIpcpLayerUp(fp)
2646059Samuraistruct fsm *fp;
2656059Samurai{
2666059Samurai  char tbuff[100];
2676059Samurai
2686059Samurai#ifdef VERBOSE
2696059Samurai  fprintf(stderr, "%s: LayerUp(%d).\r\n", fp->name, fp->state);
2706059Samurai#endif
27125630Sbrian  Prompt();
27215738Sphk  LogPrintf(LOG_LCP_BIT, "%s: LayerUp.\n", fp->name);
27321488Simp  snprintf(tbuff, sizeof(tbuff), "myaddr = %s ",
27421488Simp    inet_ntoa(IpcpInfo.want_ipaddr));
27515738Sphk  LogPrintf(LOG_LCP_BIT|LOG_LINK_BIT, " %s hisaddr = %s\n", tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
27625630Sbrian  if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask) < 0) {
27725630Sbrian     printf("unable to set ip address\n");
27825630Sbrian     return;
27925630Sbrian  }
2806059Samurai  OsLinkup();
2816059Samurai  IpcpStartReport();
2826059Samurai  StartIdleTimer();
28320365Sjkh  if (mode & MODE_ALIAS)
28420365Sjkh    SetAliasAddress(IpcpInfo.want_ipaddr);
2856059Samurai}
2866059Samurai
2876059Samuraivoid
2886059SamuraiIpcpUp()
2896059Samurai{
2906059Samurai  FsmUp(&IpcpFsm);
29115738Sphk  LogPrintf(LOG_LCP_BIT, "IPCP Up event!!\n");
2926059Samurai}
2936059Samurai
2946059Samuraivoid
2956059SamuraiIpcpOpen()
2966059Samurai{
2976059Samurai  FsmOpen(&IpcpFsm);
2986059Samurai}
2996059Samurai
3006059Samuraistatic int
3016059SamuraiAcceptableAddr(prange, ipaddr)
3026059Samuraistruct in_range *prange;
3036059Samuraistruct in_addr ipaddr;
3046059Samurai{
3056059Samurai#ifdef DEBUG
3066059Samurai  logprintf("requested = %x ", htonl(ipaddr.s_addr));
3076059Samurai  logprintf("range = %x", htonl(prange->ipaddr.s_addr));
3086059Samurai  logprintf("/%x\n", htonl(prange->mask.s_addr));
3096059Samurai  logprintf("%x, %x\n", htonl(prange->ipaddr.s_addr & prange->mask.s_addr),
3106059Samurai    htonl(ipaddr.s_addr & prange->mask.s_addr));
3116059Samurai#endif
3126059Samurai  return((prange->ipaddr.s_addr & prange->mask.s_addr) ==
3136059Samurai	(ipaddr.s_addr & prange->mask.s_addr));
3146059Samurai}
3156059Samurai
3166059Samuraistatic void
3176735SamuraiIpcpDecodeConfig(cp, plen, mode)
3186735Samuraiu_char *cp;
3196735Samuraiint plen;
3206059Samuraiint mode;
3216059Samurai{
3226735Samurai  int type, length;
3236059Samurai  u_long *lp, compproto;
3246059Samurai  struct compreq *pcomp;
32518752Sjkh  struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
3266059Samurai  char tbuff[100];
32721488Simp  char tbuff2[100];
3286059Samurai
3296059Samurai  ackp = AckBuff;
3306059Samurai  nakp = NakBuff;
3316059Samurai  rejp = RejBuff;
3326059Samurai
3336059Samurai  while (plen >= sizeof(struct fsmconfig)) {
3346059Samurai    if (plen < 0)
3356059Samurai      break;
3366059Samurai    type = *cp;
3376059Samurai    length = cp[1];
3386059Samurai    if (type <= TY_IPADDR)
33921488Simp      snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
3406059Samurai    else
34121488Simp      snprintf(tbuff, sizeof(tbuff), " ");
3426059Samurai
3436059Samurai    switch (type) {
3446059Samurai    case TY_IPADDR:		/* RFC1332 */
3456059Samurai      lp = (u_long *)(cp + 2);
3466059Samurai      ipaddr.s_addr = *lp;
34715738Sphk      LogPrintf(LOG_LCP_BIT, "%s %s\n", tbuff, inet_ntoa(ipaddr));
3486059Samurai
3496059Samurai      switch (mode) {
3506059Samurai      case MODE_REQ:
3516059Samurai	if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
3526059Samurai          /*
3536059Samurai           * If destination address is not acceptable, insist to use
3546059Samurai           * what we want to use.
3556059Samurai           */
3566059Samurai	  bcopy(cp, nakp, 2);
3576059Samurai          bcopy(&IpcpInfo.his_ipaddr.s_addr, nakp+2, length);
3586059Samurai          nakp += length;
3596059Samurai          break;
3608857Srgrimes
3616059Samurai	}
3626059Samurai	IpcpInfo.his_ipaddr = ipaddr;
3636059Samurai	bcopy(cp, ackp, length);
3646059Samurai	ackp += length;
3656059Samurai	break;
3666059Samurai      case MODE_NAK:
3676059Samurai	if (AcceptableAddr(&DefMyAddress, ipaddr)) {
3686059Samurai          /*
3696059Samurai           * Use address suggested by peer.
3706059Samurai           */
37121488Simp	  snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
37221488Simp	  LogPrintf(LOG_LCP_BIT, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
3736059Samurai	  IpcpInfo.want_ipaddr = ipaddr;
3746059Samurai	}
3756059Samurai	break;
3766059Samurai      case MODE_REJ:
3776059Samurai	IpcpInfo.his_reject |= (1 << type);
3786059Samurai	break;
3796059Samurai      }
3806059Samurai      break;
3816059Samurai    case TY_COMPPROTO:
3826059Samurai      lp = (u_long *)(cp + 2);
3836059Samurai      compproto = htonl(*lp);
38415738Sphk      LogPrintf(LOG_LCP_BIT, "%s %08x\n", tbuff, compproto);
3856059Samurai
3866059Samurai      switch (mode) {
3876059Samurai      case MODE_REQ:
3886059Samurai	if (!Acceptable(ConfVjcomp)) {
3896059Samurai	  bcopy(cp, rejp, length);
3906059Samurai	  rejp += length;
3916059Samurai	} else {
3926059Samurai	  pcomp = (struct compreq *)(cp + 2);
3936059Samurai	  switch (length) {
3946059Samurai	  case 4:	/* RFC1172 */
3956059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
3966059Samurai	      logprintf("** Peer is speaking RFC1172 compression protocol **\n");
3976059Samurai	      IpcpInfo.heis1172 = 1;
3986059Samurai	      IpcpInfo.his_compproto = compproto;
3996059Samurai	      bcopy(cp, ackp, length);
4006059Samurai	      ackp += length;
4016059Samurai	    } else {
4026059Samurai	      bcopy(cp, nakp, 2);
4036059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
4046059Samurai	      bcopy(&pcomp, nakp + 2, 2);
4056059Samurai	      nakp += length;
4066059Samurai	    }
4076059Samurai	    break;
4086059Samurai	  case 6: 	/* RFC1332 */
4096059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
4106059Samurai	        && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
4116059Samurai	      IpcpInfo.his_compproto = compproto;
4126059Samurai	      IpcpInfo.heis1172 = 0;
4136059Samurai	      bcopy(cp, ackp, length);
4146059Samurai	      ackp += length;
4156059Samurai	    } else {
4166059Samurai	      bcopy(cp, nakp, 2);
4176059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
4186059Samurai	      pcomp->slots = MAX_STATES - 1;
4196059Samurai	      pcomp->compcid = 0;
4206059Samurai	      bcopy(&pcomp, nakp + 2, sizeof(pcomp));
4216059Samurai	      nakp += length;
4226059Samurai	    }
4236059Samurai	    break;
4246059Samurai	  default:
4256059Samurai	    bcopy(cp, rejp, length);
4266059Samurai	    rejp += length;
4276059Samurai	    break;
4286059Samurai	  }
4296059Samurai	}
4306059Samurai	break;
4316059Samurai      case MODE_NAK:
43215738Sphk	LogPrintf(LOG_LCP_BIT, "%s changing compproto: %08x --> %08x\n",
4336059Samurai	  tbuff, IpcpInfo.want_compproto, compproto);
4346059Samurai	IpcpInfo.want_compproto = compproto;
4356059Samurai	break;
4366059Samurai      case MODE_REJ:
4376059Samurai	IpcpInfo.his_reject |= (1 << type);
4386059Samurai	break;
4396059Samurai      }
4406059Samurai      break;
4416059Samurai    case TY_IPADDRS:	/* RFC1172 */
4426059Samurai      lp = (u_long *)(cp + 2);
4436059Samurai      ipaddr.s_addr = *lp;
4446059Samurai      lp = (u_long *)(cp + 6);
4456059Samurai      dstipaddr.s_addr = *lp;
44615738Sphk      LogPrintf(LOG_LCP_BIT, "%s %s, ", tbuff, inet_ntoa(ipaddr));
44715738Sphk      LogPrintf(LOG_LCP_BIT, "%s\n", inet_ntoa(dstipaddr));
4486059Samurai
4496059Samurai      switch (mode) {
4506059Samurai      case MODE_REQ:
4516059Samurai	IpcpInfo.his_ipaddr = ipaddr;
4526059Samurai	IpcpInfo.want_ipaddr = dstipaddr;
4536059Samurai	bcopy(cp, ackp, length);
4546059Samurai	ackp += length;
4556059Samurai	break;
4566059Samurai      case MODE_NAK:
45715738Sphk	LogPrintf(LOG_LCP_BIT, "%s changing address: %s ",
4586059Samurai	  tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
45915738Sphk	LogPrintf(LOG_LCP_BIT, "--> %s\n", inet_ntoa(ipaddr));
4606059Samurai	IpcpInfo.want_ipaddr = ipaddr;
4616059Samurai	IpcpInfo.his_ipaddr = dstipaddr;
4626059Samurai	break;
4636059Samurai      case MODE_REJ:
4646059Samurai	IpcpInfo.his_reject |= (1 << type);
4656059Samurai	break;
4666059Samurai      }
4676059Samurai      break;
46818752Sjkh
46918752Sjkh /*
47018752Sjkh  * MS extensions for MS's PPP
47118752Sjkh  */
47218752Sjkh
47318752Sjkh#ifdef MSEXT
47418752Sjkh    case TY_PRIMARY_DNS:   /* MS PPP DNS negotiation hack */
47518752Sjkh    case TY_SECONDARY_DNS:
47618752Sjkh      if( !Enabled( ConfMSExt ) ) {
47718752Sjkh	LogPrintf( LOG_LCP, "MS NS req - rejected - msext disabled\n" );
47818752Sjkh	IpcpInfo.my_reject |= ( 1 << type );
47918752Sjkh	bcopy(cp, rejp, length);
48018752Sjkh	rejp += length;
48118752Sjkh	break;
48218752Sjkh      }
48318752Sjkh      switch( mode ){
48418752Sjkh      case MODE_REQ:
48518752Sjkh	lp = (u_long *)(cp + 2);
48618752Sjkh	dnsstuff.s_addr = *lp;
48718752Sjkh	ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS)?1:0)].s_addr;
48818752Sjkh	if( dnsstuff.s_addr != ms_info_req.s_addr )
48918752Sjkh	{
49018752Sjkh	  /*
49118752Sjkh	   So the client has got the DNS stuff wrong (first request)
49218752Sjkh	   so well tell 'em how it is
49318752Sjkh	  */
49418752Sjkh	  bcopy( cp, nakp, 2 );  /* copy first two (type/length) */
49518752Sjkh	  LogPrintf( LOG_LCP, "MS NS req %d:%s->%s - nak\n",
49618752Sjkh		type,
49718752Sjkh		inet_ntoa( dnsstuff ),
49818752Sjkh		inet_ntoa( ms_info_req ));
49918752Sjkh	  bcopy( &ms_info_req, nakp+2, length );
50018752Sjkh	  nakp += length;
50118752Sjkh	  break;
50218752Sjkh	}
50318752Sjkh	  /*
50418752Sjkh	   Otherwise they have it right (this time) so we send
50518752Sjkh	   a ack packet back confirming it... end of story
50618752Sjkh	  */
50718752Sjkh	LogPrintf( LOG_LCP, "MS NS req %d:%s ok - ack\n",
50818752Sjkh		type,
50918752Sjkh		inet_ntoa( ms_info_req ));
51018752Sjkh	bcopy( cp, ackp, length );
51118752Sjkh	ackp += length;
51218752Sjkh	break;
51318752Sjkh      case MODE_NAK: /* what does this mean?? */
51418752Sjkh	LogPrintf(LOG_LCP, "MS NS req %d - NAK??\n", type );
51518752Sjkh	break;
51618752Sjkh      case MODE_REJ: /* confused?? me to :) */
51718752Sjkh	LogPrintf(LOG_LCP, "MS NS req %d - REJ??\n", type );
51818752Sjkh	break;
51918752Sjkh      }
52018752Sjkh      break;
52118752Sjkh
52218752Sjkh    case TY_PRIMARY_NBNS:   /* MS PPP NetBIOS nameserver hack */
52318752Sjkh    case TY_SECONDARY_NBNS:
52418752Sjkh    if( !Enabled( ConfMSExt ) ) {
52518752Sjkh      LogPrintf( LOG_LCP, "MS NBNS req - rejected - msext disabled\n" );
52618752Sjkh      IpcpInfo.my_reject |= ( 1 << type );
52718752Sjkh      bcopy( cp, rejp, length );
52818752Sjkh      rejp += length;
52918752Sjkh      break;
53018752Sjkh    }
53118752Sjkh      switch( mode ){
53218752Sjkh      case MODE_REQ:
53318752Sjkh	lp = (u_long *)(cp + 2);
53418752Sjkh	dnsstuff.s_addr = *lp;
53518752Sjkh	ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS)?1:0)].s_addr;
53618752Sjkh	if( dnsstuff.s_addr != ms_info_req.s_addr )
53718752Sjkh	{
53818752Sjkh	  bcopy( cp, nakp, 2 );
53918752Sjkh	  bcopy( &ms_info_req.s_addr , nakp+2, length );
54018752Sjkh	  LogPrintf( LOG_LCP, "MS NBNS req %d:%s->%s - nak\n",
54118752Sjkh		type,
54218752Sjkh		inet_ntoa( dnsstuff ),
54318752Sjkh		inet_ntoa( ms_info_req ));
54418752Sjkh	  nakp += length;
54518752Sjkh	  break;
54618752Sjkh	}
54718752Sjkh	LogPrintf( LOG_LCP, "MS NBNS req %d:%s ok - ack\n",
54818752Sjkh		type,
54918752Sjkh		inet_ntoa( ms_info_req ));
55018752Sjkh	bcopy( cp, ackp, length );
55118752Sjkh	ackp += length;
55218752Sjkh	break;
55318752Sjkh      case MODE_NAK:
55418752Sjkh	LogPrintf( LOG_LCP, "MS NBNS req %d - NAK??\n", type );
55518752Sjkh	break;
55618752Sjkh      case MODE_REJ:
55718752Sjkh	LogPrintf( LOG_LCP, "MS NBNS req %d - REJ??\n", type );
55818752Sjkh	break;
55918752Sjkh      }
56018752Sjkh      break;
56118752Sjkh
56218752Sjkh#endif /* MSEXT */
56318752Sjkh
5646059Samurai    default:
5656059Samurai      IpcpInfo.my_reject |= (1 << type);
5666059Samurai      bcopy(cp, rejp, length);
5676059Samurai      rejp += length;
5686059Samurai      break;
5696059Samurai    }
5706059Samurai    plen -= length;
5716059Samurai    cp += length;
5726059Samurai  }
5736059Samurai}
5746059Samurai
5756059Samuraivoid
5766059SamuraiIpcpInput(struct mbuf *bp)
5776059Samurai{
5786059Samurai  FsmInput(&IpcpFsm, bp);
5796059Samurai}
580