ipcp.c revision 28461
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 *
2028461Sbrian * $Id: ipcp.c,v 1.24 1997/08/19 01:10:20 brian 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"
3726142Sbrian#include "loadalias.h"
386059Samurai#include "vars.h"
396059Samurai
406059Samuraiextern void PutConfValue();
416059Samuraiextern void Prompt();
426059Samuraiextern struct in_addr ifnetmask;
436059Samurai
446059Samuraistruct ipcpstate IpcpInfo;
4528394Sbrianstruct in_range DefMyAddress, DefHisAddress;
4628394Sbrianstruct in_addr TriggerAddress;
4728394Sbrianint HaveTriggerAddress;
486059Samurai
4926516Sbrian#ifndef NOMSEXT
5018752Sjkhstruct in_addr ns_entries[2], nbns_entries[2];
5126516Sbrian#endif
5218752Sjkh
5326516Sbrianstatic void IpcpSendConfigReq(struct fsm *);
5426516Sbrianstatic void IpcpSendTerminateAck(struct fsm *);
5526516Sbrianstatic void IpcpSendTerminateReq(struct fsm *);
5626516Sbrianstatic void IpcpDecodeConfig(u_char *, int, int);
5726516Sbrianstatic void IpcpLayerStart(struct fsm *);
5826516Sbrianstatic void IpcpLayerFinish(struct fsm *);
5926516Sbrianstatic void IpcpLayerUp(struct fsm *);
6026516Sbrianstatic void IpcpLayerDown(struct fsm *);
6126516Sbrianstatic void IpcpInitRestartCounter(struct fsm *);
626059Samurai
637001Samuraistruct pppTimer IpcpReportTimer;
646059Samurai
656059Samuraistatic int lastInOctets, lastOutOctets;
666059Samurai
676059Samurai#define	REJECTED(p, x)	(p->his_reject & (1<<x))
686059Samurai
696059Samuraistruct fsm IpcpFsm = {
706059Samurai  "IPCP",
716059Samurai  PROTO_IPCP,
726059Samurai  IPCP_MAXCODE,
736059Samurai  OPEN_ACTIVE,
746059Samurai  ST_INITIAL,
756059Samurai  0, 0, 0,
766059Samurai
776059Samurai  0,
786059Samurai  { 0, 0, 0, NULL, NULL, NULL },
7928461Sbrian  { 0, 0, 0, NULL, NULL, NULL },
8028461Sbrian  LogIPCP,
816059Samurai
826059Samurai  IpcpLayerUp,
836059Samurai  IpcpLayerDown,
846059Samurai  IpcpLayerStart,
856059Samurai  IpcpLayerFinish,
866059Samurai  IpcpInitRestartCounter,
876059Samurai  IpcpSendConfigReq,
886059Samurai  IpcpSendTerminateReq,
896059Samurai  IpcpSendTerminateAck,
906059Samurai  IpcpDecodeConfig,
916059Samurai};
926059Samurai
936059Samuraistatic char *cftypes[] = {
946059Samurai  "???", "IPADDRS", "COMPPROTO", "IPADDR",
956059Samurai};
966059Samurai
976059Samurai/*
986059Samurai * Function called every second. Updates connection period and idle period,
996059Samurai * also update LQR information.
1006059Samurai */
1016059Samuraistatic void
1026059SamuraiIpcpReportFunc()
1036059Samurai{
1046059Samurai  ipConnectSecs++;
1056059Samurai  if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets)
1066059Samurai    ipIdleSecs++;
1076059Samurai  lastInOctets = ipInOctets;
1086059Samurai  lastOutOctets = ipOutOctets;
1096059Samurai  StopTimer(&IpcpReportTimer);
1106059Samurai  IpcpReportTimer.state = TIMER_STOPPED;
1116059Samurai  StartTimer(&IpcpReportTimer);
1126059Samurai}
1136059Samurai
1146059Samuraistatic void
1156059SamuraiIpcpStartReport()
1166059Samurai{
1176059Samurai  ipIdleSecs = ipConnectSecs = 0;
1186059Samurai  StopTimer(&IpcpReportTimer);
1196059Samurai  IpcpReportTimer.state = TIMER_STOPPED;
1206059Samurai  IpcpReportTimer.load = SECTICKS;
1216059Samurai  IpcpReportTimer.func = IpcpReportFunc;
1226059Samurai  StartTimer(&IpcpReportTimer);
1236059Samurai}
1246059Samurai
12525630Sbrianint
1266059SamuraiReportIpcpStatus()
1276059Samurai{
1286059Samurai  struct ipcpstate *icp = &IpcpInfo;
1296059Samurai  struct fsm *fp = &IpcpFsm;
1306059Samurai
13126516Sbrian  if (!VarTerm)
13226516Sbrian    return 1;
13326516Sbrian  fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
13426516Sbrian  fprintf(VarTerm, " his side: %s, %lx\n",
1356059Samurai     inet_ntoa(icp->his_ipaddr), icp->his_compproto);
13626516Sbrian  fprintf(VarTerm, " my  side: %s, %lx\n",
1376059Samurai     inet_ntoa(icp->want_ipaddr), icp->want_compproto);
13826516Sbrian  fprintf(VarTerm, "connected: %d secs, idle: %d secs\n\n", ipConnectSecs, ipIdleSecs);
13926516Sbrian  fprintf(VarTerm, "Defaults:\n");
14026516Sbrian  fprintf(VarTerm, " My Address:  %s/%d\n",
1416059Samurai     inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
14226516Sbrian  fprintf(VarTerm, " His Address: %s/%d\n",
1436059Samurai     inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
14428394Sbrian  if (HaveTriggerAddress)
14528394Sbrian     fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress));
14628394Sbrian  else
14728394Sbrian     fprintf(VarTerm, " Negotiation(trigger): MYADDR\n");
14826516Sbrian
14926516Sbrian  return 0;
1506059Samurai}
1516059Samurai
1526059Samuraivoid
1536059SamuraiIpcpDefAddress()
1546059Samurai{
1556059Samurai  struct hostent *hp;
1566059Samurai  char name[200];
1576059Samurai
1586059Samurai  bzero(&DefMyAddress, sizeof(DefMyAddress));
1596059Samurai  bzero(&DefHisAddress, sizeof(DefHisAddress));
16028394Sbrian  TriggerAddress.s_addr = 0;
16128394Sbrian  HaveTriggerAddress = 0;
1626059Samurai  if (gethostname(name, sizeof(name)) == 0) {
1636059Samurai      hp = gethostbyname(name);
1646059Samurai      if (hp && hp->h_addrtype == AF_INET) {
1656059Samurai	bcopy(hp->h_addr, (char *)&DefMyAddress.ipaddr.s_addr, hp->h_length);
1666059Samurai      }
1676059Samurai  }
1686059Samurai}
1696059Samurai
1706059Samuraivoid
1716059SamuraiIpcpInit()
1726059Samurai{
1736059Samurai  struct ipcpstate *icp = &IpcpInfo;
1746059Samurai
1756059Samurai  FsmInit(&IpcpFsm);
1766059Samurai  bzero(icp, sizeof(struct ipcpstate));
1776059Samurai  if ((mode & MODE_DEDICATED) && !dstsystem) {
1786059Samurai    icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
1796059Samurai  } else {
1806059Samurai    icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
1816059Samurai    icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
1826059Samurai  }
1839440Samurai
1849440Samurai  /*
1859440Samurai   * Some implementation of PPP are:
1869440Samurai   *  Starting a negotiaion by require sending *special* value as my address,
1879440Samurai   *  even though standard of PPP is defined full negotiation based.
1889440Samurai   *  (e.g. "0.0.0.0" or Not "0.0.0.0")
1899440Samurai   */
19028394Sbrian  if (HaveTriggerAddress) {
19128394Sbrian    icp->want_ipaddr.s_addr = TriggerAddress.s_addr;
19228461Sbrian    LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress));
1939440Samurai  }
1949440Samurai
1956059Samurai  if (Enabled(ConfVjcomp))
1966059Samurai    icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8);
1976059Samurai  else
1986059Samurai    icp->want_compproto = 0;
1996059Samurai  icp->heis1172 = 0;
2006059Samurai  IpcpFsm.maxconfig = 10;
2016059Samurai}
2026059Samurai
2036059Samuraistatic void
2046059SamuraiIpcpInitRestartCounter(fp)
2056059Samuraistruct fsm *fp;
2066059Samurai{
2076735Samurai  fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
2086059Samurai  fp->restart = 5;
2096059Samurai}
2106059Samurai
2116059Samuraistatic void
2126059SamuraiIpcpSendConfigReq(fp)
2136059Samuraistruct fsm *fp;
2146059Samurai{
2156059Samurai  u_char *cp;
2166059Samurai  struct ipcpstate *icp = &IpcpInfo;
2176059Samurai
2186059Samurai  cp = ReqBuff;
21928461Sbrian  LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
2206735Samurai  if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR))
2216735Samurai    PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr));
2226059Samurai  if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
2236059Samurai    if (icp->heis1172)
2246059Samurai      PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16);
2256059Samurai    else
2266059Samurai      PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
2276059Samurai  }
2286059Samurai  FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
2296059Samurai}
2306059Samurai
2316059Samuraistatic void
2326059SamuraiIpcpSendTerminateReq(fp)
2336059Samuraistruct fsm *fp;
2346059Samurai{
2356059Samurai  /* XXX: No code yet */
2366059Samurai}
2376059Samurai
2386059Samuraistatic void
2396059SamuraiIpcpSendTerminateAck(fp)
2406059Samuraistruct fsm *fp;
2416059Samurai{
24228461Sbrian  LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
2436059Samurai  FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2446059Samurai}
2456059Samurai
2466059Samuraistatic void
2476059SamuraiIpcpLayerStart(fp)
2486059Samuraistruct fsm *fp;
2496059Samurai{
25028461Sbrian  LogPrintf(LogIPCP, "IpcpLayerStart.\n");
2516059Samurai}
2526059Samurai
2536059Samuraistatic void
2546059SamuraiIpcpLayerFinish(fp)
2556059Samuraistruct fsm *fp;
2566059Samurai{
25728461Sbrian  LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
25826098Sbrian  reconnect(RECON_FALSE);
2596059Samurai  LcpClose();
2606059Samurai  NewPhase(PHASE_TERMINATE);
2616059Samurai}
2626059Samurai
2636059Samuraistatic void
2646059SamuraiIpcpLayerDown(fp)
2656059Samuraistruct fsm *fp;
2666059Samurai{
26728461Sbrian  LogPrintf(LogIPCP, "IpcpLayerDown.\n");
2686059Samurai  StopTimer(&IpcpReportTimer);
2696059Samurai}
2706059Samurai
2716059Samurai/*
2726059Samurai *  Called when IPCP has reached to OPEN state
2736059Samurai */
2746059Samuraistatic void
2756059SamuraiIpcpLayerUp(fp)
2766059Samuraistruct fsm *fp;
2776059Samurai{
2786059Samurai  char tbuff[100];
2796059Samurai
28025630Sbrian  Prompt();
28128461Sbrian  LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
28221488Simp  snprintf(tbuff, sizeof(tbuff), "myaddr = %s ",
28321488Simp    inet_ntoa(IpcpInfo.want_ipaddr));
28428461Sbrian  LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
28526516Sbrian            tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
28625630Sbrian  if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask) < 0) {
28726516Sbrian    if (VarTerm)
28826516Sbrian      LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
28926516Sbrian    return;
29025630Sbrian  }
29127763Sbrian  if (mode & MODE_ALIAS)
29227763Sbrian    VarSetPacketAliasAddress(IpcpInfo.want_ipaddr);
2936059Samurai  OsLinkup();
2946059Samurai  IpcpStartReport();
2956059Samurai  StartIdleTimer();
2966059Samurai}
2976059Samurai
2986059Samuraivoid
2996059SamuraiIpcpUp()
3006059Samurai{
3016059Samurai  FsmUp(&IpcpFsm);
30228461Sbrian  LogPrintf(LogIPCP, "IPCP Up event!!\n");
3036059Samurai}
3046059Samurai
3056059Samuraivoid
3066059SamuraiIpcpOpen()
3076059Samurai{
3086059Samurai  FsmOpen(&IpcpFsm);
3096059Samurai}
3106059Samurai
3116059Samuraistatic int
3126059SamuraiAcceptableAddr(prange, ipaddr)
3136059Samuraistruct in_range *prange;
3146059Samuraistruct in_addr ipaddr;
3156059Samurai{
31626516Sbrian  LogPrintf(LogDEBUG, "requested = %x ", htonl(ipaddr.s_addr));
31726516Sbrian  LogPrintf(LogDEBUG, "range = %x", htonl(prange->ipaddr.s_addr));
31826516Sbrian  LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
31926516Sbrian  LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
32026516Sbrian            mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
32125661Sbrian  return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
32225661Sbrian	(ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
3236059Samurai}
3246059Samurai
3256059Samuraistatic void
3266735SamuraiIpcpDecodeConfig(cp, plen, mode)
3276735Samuraiu_char *cp;
3286735Samuraiint plen;
3296059Samuraiint mode;
3306059Samurai{
3316735Samurai  int type, length;
3326059Samurai  u_long *lp, compproto;
3336059Samurai  struct compreq *pcomp;
33418752Sjkh  struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
3356059Samurai  char tbuff[100];
33621488Simp  char tbuff2[100];
3376059Samurai
3386059Samurai  ackp = AckBuff;
3396059Samurai  nakp = NakBuff;
3406059Samurai  rejp = RejBuff;
3416059Samurai
3426059Samurai  while (plen >= sizeof(struct fsmconfig)) {
3436059Samurai    if (plen < 0)
3446059Samurai      break;
3456059Samurai    type = *cp;
3466059Samurai    length = cp[1];
3476059Samurai    if (type <= TY_IPADDR)
34821488Simp      snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
3496059Samurai    else
35021488Simp      snprintf(tbuff, sizeof(tbuff), " ");
3516059Samurai
3526059Samurai    switch (type) {
3536059Samurai    case TY_IPADDR:		/* RFC1332 */
3546059Samurai      lp = (u_long *)(cp + 2);
3556059Samurai      ipaddr.s_addr = *lp;
35628461Sbrian      LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
3576059Samurai
3586059Samurai      switch (mode) {
3596059Samurai      case MODE_REQ:
3606059Samurai	if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
3616059Samurai          /*
3626059Samurai           * If destination address is not acceptable, insist to use
3636059Samurai           * what we want to use.
3646059Samurai           */
3656059Samurai	  bcopy(cp, nakp, 2);
3666059Samurai          bcopy(&IpcpInfo.his_ipaddr.s_addr, nakp+2, length);
3676059Samurai          nakp += length;
3686059Samurai          break;
3698857Srgrimes
3706059Samurai	}
3716059Samurai	IpcpInfo.his_ipaddr = ipaddr;
3726059Samurai	bcopy(cp, ackp, length);
3736059Samurai	ackp += length;
3746059Samurai	break;
3756059Samurai      case MODE_NAK:
3766059Samurai	if (AcceptableAddr(&DefMyAddress, ipaddr)) {
3776059Samurai          /*
3786059Samurai           * Use address suggested by peer.
3796059Samurai           */
38021488Simp	  snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
38128461Sbrian	  LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
3826059Samurai	  IpcpInfo.want_ipaddr = ipaddr;
3836059Samurai	}
3846059Samurai	break;
3856059Samurai      case MODE_REJ:
3866059Samurai	IpcpInfo.his_reject |= (1 << type);
3876059Samurai	break;
3886059Samurai      }
3896059Samurai      break;
3906059Samurai    case TY_COMPPROTO:
3916059Samurai      lp = (u_long *)(cp + 2);
3926059Samurai      compproto = htonl(*lp);
39328461Sbrian      LogPrintf(LogIPCP, "%s %08x\n", tbuff, compproto);
3946059Samurai
3956059Samurai      switch (mode) {
3966059Samurai      case MODE_REQ:
3976059Samurai	if (!Acceptable(ConfVjcomp)) {
3986059Samurai	  bcopy(cp, rejp, length);
3996059Samurai	  rejp += length;
4006059Samurai	} else {
4016059Samurai	  pcomp = (struct compreq *)(cp + 2);
4026059Samurai	  switch (length) {
4036059Samurai	  case 4:	/* RFC1172 */
4046059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
40526940Sbrian	      LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
4066059Samurai	      IpcpInfo.heis1172 = 1;
4076059Samurai	      IpcpInfo.his_compproto = compproto;
4086059Samurai	      bcopy(cp, ackp, length);
4096059Samurai	      ackp += length;
4106059Samurai	    } else {
4116059Samurai	      bcopy(cp, nakp, 2);
4126059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
4136059Samurai	      bcopy(&pcomp, nakp + 2, 2);
4146059Samurai	      nakp += length;
4156059Samurai	    }
4166059Samurai	    break;
4176059Samurai	  case 6: 	/* RFC1332 */
4186059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
4196059Samurai	        && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
4206059Samurai	      IpcpInfo.his_compproto = compproto;
4216059Samurai	      IpcpInfo.heis1172 = 0;
4226059Samurai	      bcopy(cp, ackp, length);
4236059Samurai	      ackp += length;
4246059Samurai	    } else {
4256059Samurai	      bcopy(cp, nakp, 2);
4266059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
4276059Samurai	      pcomp->slots = MAX_STATES - 1;
4286059Samurai	      pcomp->compcid = 0;
4296059Samurai	      bcopy(&pcomp, nakp + 2, sizeof(pcomp));
4306059Samurai	      nakp += length;
4316059Samurai	    }
4326059Samurai	    break;
4336059Samurai	  default:
4346059Samurai	    bcopy(cp, rejp, length);
4356059Samurai	    rejp += length;
4366059Samurai	    break;
4376059Samurai	  }
4386059Samurai	}
4396059Samurai	break;
4406059Samurai      case MODE_NAK:
44128461Sbrian	LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
4426059Samurai	  tbuff, IpcpInfo.want_compproto, compproto);
4436059Samurai	IpcpInfo.want_compproto = compproto;
4446059Samurai	break;
4456059Samurai      case MODE_REJ:
4466059Samurai	IpcpInfo.his_reject |= (1 << type);
4476059Samurai	break;
4486059Samurai      }
4496059Samurai      break;
4506059Samurai    case TY_IPADDRS:	/* RFC1172 */
4516059Samurai      lp = (u_long *)(cp + 2);
4526059Samurai      ipaddr.s_addr = *lp;
4536059Samurai      lp = (u_long *)(cp + 6);
4546059Samurai      dstipaddr.s_addr = *lp;
45528461Sbrian      LogPrintf(LogIPCP, "%s %s, ", tbuff, inet_ntoa(ipaddr));
45628461Sbrian      LogPrintf(LogIPCP, "%s\n", inet_ntoa(dstipaddr));
4576059Samurai
4586059Samurai      switch (mode) {
4596059Samurai      case MODE_REQ:
4606059Samurai	IpcpInfo.his_ipaddr = ipaddr;
4616059Samurai	IpcpInfo.want_ipaddr = dstipaddr;
4626059Samurai	bcopy(cp, ackp, length);
4636059Samurai	ackp += length;
4646059Samurai	break;
4656059Samurai      case MODE_NAK:
46628461Sbrian	LogPrintf(LogIPCP, "%s changing address: %s ",
4676059Samurai	  tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
46828461Sbrian	LogPrintf(LogIPCP, "--> %s\n", inet_ntoa(ipaddr));
4696059Samurai	IpcpInfo.want_ipaddr = ipaddr;
4706059Samurai	IpcpInfo.his_ipaddr = dstipaddr;
4716059Samurai	break;
4726059Samurai      case MODE_REJ:
4736059Samurai	IpcpInfo.his_reject |= (1 << type);
4746059Samurai	break;
4756059Samurai      }
4766059Samurai      break;
47718752Sjkh
47818752Sjkh /*
47918752Sjkh  * MS extensions for MS's PPP
48018752Sjkh  */
48118752Sjkh
48226516Sbrian#ifndef NOMSEXT
48318752Sjkh    case TY_PRIMARY_DNS:   /* MS PPP DNS negotiation hack */
48418752Sjkh    case TY_SECONDARY_DNS:
48518752Sjkh      if( !Enabled( ConfMSExt ) ) {
48628461Sbrian	LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
48718752Sjkh	IpcpInfo.my_reject |= ( 1 << type );
48818752Sjkh	bcopy(cp, rejp, length);
48918752Sjkh	rejp += length;
49018752Sjkh	break;
49118752Sjkh      }
49218752Sjkh      switch( mode ){
49318752Sjkh      case MODE_REQ:
49418752Sjkh	lp = (u_long *)(cp + 2);
49518752Sjkh	dnsstuff.s_addr = *lp;
49618752Sjkh	ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS)?1:0)].s_addr;
49718752Sjkh	if( dnsstuff.s_addr != ms_info_req.s_addr )
49818752Sjkh	{
49918752Sjkh	  /*
50018752Sjkh	   So the client has got the DNS stuff wrong (first request)
50118752Sjkh	   so well tell 'em how it is
50218752Sjkh	  */
50318752Sjkh	  bcopy( cp, nakp, 2 );  /* copy first two (type/length) */
50428461Sbrian	  LogPrintf( LogIPCP, "MS NS req %d:%s->%s - nak\n",
50518752Sjkh		type,
50618752Sjkh		inet_ntoa( dnsstuff ),
50718752Sjkh		inet_ntoa( ms_info_req ));
50818752Sjkh	  bcopy( &ms_info_req, nakp+2, length );
50918752Sjkh	  nakp += length;
51018752Sjkh	  break;
51118752Sjkh	}
51218752Sjkh	  /*
51318752Sjkh	   Otherwise they have it right (this time) so we send
51418752Sjkh	   a ack packet back confirming it... end of story
51518752Sjkh	  */
51628461Sbrian	LogPrintf( LogIPCP, "MS NS req %d:%s ok - ack\n",
51718752Sjkh		type,
51818752Sjkh		inet_ntoa( ms_info_req ));
51918752Sjkh	bcopy( cp, ackp, length );
52018752Sjkh	ackp += length;
52118752Sjkh	break;
52218752Sjkh      case MODE_NAK: /* what does this mean?? */
52328461Sbrian	LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type );
52418752Sjkh	break;
52518752Sjkh      case MODE_REJ: /* confused?? me to :) */
52628461Sbrian	LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type );
52718752Sjkh	break;
52818752Sjkh      }
52918752Sjkh      break;
53018752Sjkh
53118752Sjkh    case TY_PRIMARY_NBNS:   /* MS PPP NetBIOS nameserver hack */
53218752Sjkh    case TY_SECONDARY_NBNS:
53318752Sjkh    if( !Enabled( ConfMSExt ) ) {
53428461Sbrian      LogPrintf( LogIPCP, "MS NBNS req - rejected - msext disabled\n" );
53518752Sjkh      IpcpInfo.my_reject |= ( 1 << type );
53618752Sjkh      bcopy( cp, rejp, length );
53718752Sjkh      rejp += length;
53818752Sjkh      break;
53918752Sjkh    }
54018752Sjkh      switch( mode ){
54118752Sjkh      case MODE_REQ:
54218752Sjkh	lp = (u_long *)(cp + 2);
54318752Sjkh	dnsstuff.s_addr = *lp;
54418752Sjkh	ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS)?1:0)].s_addr;
54518752Sjkh	if( dnsstuff.s_addr != ms_info_req.s_addr )
54618752Sjkh	{
54718752Sjkh	  bcopy( cp, nakp, 2 );
54818752Sjkh	  bcopy( &ms_info_req.s_addr , nakp+2, length );
54928461Sbrian	  LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
55018752Sjkh		type,
55118752Sjkh		inet_ntoa( dnsstuff ),
55218752Sjkh		inet_ntoa( ms_info_req ));
55318752Sjkh	  nakp += length;
55418752Sjkh	  break;
55518752Sjkh	}
55628461Sbrian	LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
55718752Sjkh		type,
55818752Sjkh		inet_ntoa( ms_info_req ));
55918752Sjkh	bcopy( cp, ackp, length );
56018752Sjkh	ackp += length;
56118752Sjkh	break;
56218752Sjkh      case MODE_NAK:
56328461Sbrian	LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type );
56418752Sjkh	break;
56518752Sjkh      case MODE_REJ:
56628461Sbrian	LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type );
56718752Sjkh	break;
56818752Sjkh      }
56918752Sjkh      break;
57018752Sjkh
57126516Sbrian#endif
57218752Sjkh
5736059Samurai    default:
5746059Samurai      IpcpInfo.my_reject |= (1 << type);
5756059Samurai      bcopy(cp, rejp, length);
5766059Samurai      rejp += length;
5776059Samurai      break;
5786059Samurai    }
5796059Samurai    plen -= length;
5806059Samurai    cp += length;
5816059Samurai  }
5826059Samurai}
5836059Samurai
5846059Samuraivoid
5856059SamuraiIpcpInput(struct mbuf *bp)
5866059Samurai{
5876059Samurai  FsmInput(&IpcpFsm, bp);
5886059Samurai}
589