ipcp.c revision 31514
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 *
2031514Sbrian * $Id: ipcp.c,v 1.38 1997/11/22 03:37:34 brian Exp $
218857Srgrimes *
226059Samurai *	TODO:
236059Samurai *		o More RFC1772 backwoard compatibility
246059Samurai */
2530715Sbrian#include <sys/param.h>
266059Samurai#include <netinet/in_systm.h>
2729048Sbrian#include <netinet/in.h>
286059Samurai#include <netinet/ip.h>
296059Samurai#include <arpa/inet.h>
306059Samurai#include <sys/socket.h>
3130715Sbrian#include <netdb.h>
3230715Sbrian
3329048Sbrian#include <limits.h>
3430715Sbrian#include <stdio.h>
3530715Sbrian#include <string.h>
3631272Sbrian#include <time.h>
3730715Sbrian#include <unistd.h>
3830715Sbrian
3931343Sbrian#include "command.h"
4030715Sbrian#include "mbuf.h"
4130715Sbrian#include "log.h"
4230715Sbrian#include "defs.h"
4330715Sbrian#include "timer.h"
4429048Sbrian#include "fsm.h"
4529048Sbrian#include "lcpproto.h"
4629048Sbrian#include "lcp.h"
4729048Sbrian#include "ipcp.h"
486059Samurai#include "slcompress.h"
496059Samurai#include "os.h"
506059Samurai#include "phase.h"
5126142Sbrian#include "loadalias.h"
526059Samurai#include "vars.h"
5330715Sbrian#include "vjcomp.h"
5430733Sbrian#include "ip.h"
5531272Sbrian#include "throughput.h"
566059Samurai
5730715Sbrian#ifndef NOMSEXT
5830715Sbrianstruct in_addr ns_entries[2];
5930715Sbrianstruct in_addr nbns_entries[2];
6030715Sbrian#endif
616059Samurai
626059Samuraistruct ipcpstate IpcpInfo;
6330715Sbrianstruct in_range  DefMyAddress;
6430715Sbrianstruct in_range  DefHisAddress;
6530715Sbrianstruct in_addr   TriggerAddress;
6628394Sbrianint HaveTriggerAddress;
676059Samurai
6826516Sbrianstatic void IpcpSendConfigReq(struct fsm *);
6926516Sbrianstatic void IpcpSendTerminateAck(struct fsm *);
7026516Sbrianstatic void IpcpSendTerminateReq(struct fsm *);
7126516Sbrianstatic void IpcpDecodeConfig(u_char *, int, int);
7226516Sbrianstatic void IpcpLayerStart(struct fsm *);
7326516Sbrianstatic void IpcpLayerFinish(struct fsm *);
7426516Sbrianstatic void IpcpLayerUp(struct fsm *);
7526516Sbrianstatic void IpcpLayerDown(struct fsm *);
7626516Sbrianstatic void IpcpInitRestartCounter(struct fsm *);
776059Samurai
786059Samurai#define	REJECTED(p, x)	(p->his_reject & (1<<x))
796059Samurai
806059Samuraistruct fsm IpcpFsm = {
816059Samurai  "IPCP",
826059Samurai  PROTO_IPCP,
836059Samurai  IPCP_MAXCODE,
846059Samurai  OPEN_ACTIVE,
856059Samurai  ST_INITIAL,
866059Samurai  0, 0, 0,
876059Samurai
886059Samurai  0,
8928679Sbrian  {0, 0, 0, NULL, NULL, NULL},
9028679Sbrian  {0, 0, 0, NULL, NULL, NULL},
9128461Sbrian  LogIPCP,
926059Samurai
936059Samurai  IpcpLayerUp,
946059Samurai  IpcpLayerDown,
956059Samurai  IpcpLayerStart,
966059Samurai  IpcpLayerFinish,
976059Samurai  IpcpInitRestartCounter,
986059Samurai  IpcpSendConfigReq,
996059Samurai  IpcpSendTerminateReq,
1006059Samurai  IpcpSendTerminateAck,
1016059Samurai  IpcpDecodeConfig,
1026059Samurai};
1036059Samurai
10431343Sbrianstatic const char *cftypes[] = {
10531171Sbrian  /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
10631171Sbrian  "???",
10731171Sbrian  "IPADDRS",	/* 1: IP-Addresses */	/* deprecated */
10831171Sbrian  "COMPPROTO",	/* 2: IP-Compression-Protocol */
10931171Sbrian  "IPADDR",	/* 3: IP-Address */
1106059Samurai};
1116059Samurai
11231171Sbrian#define NCFTYPES (sizeof(cftypes)/sizeof(char *))
11331171Sbrian
11431343Sbrianstatic const char *cftypes128[] = {
11531171Sbrian  /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
11631171Sbrian  "???",
11731171Sbrian  "PRIDNS",	/* 129: Primary DNS Server Address */
11831171Sbrian  "PRINBNS",	/* 130: Primary NBNS Server Address */
11931171Sbrian  "SECDNS",	/* 131: Secondary DNS Server Address */
12031171Sbrian  "SECNBNS",	/* 132: Secondary NBNS Server Address */
12131171Sbrian};
12231171Sbrian
12331171Sbrian#define NCFTYPES128 (sizeof(cftypes)/sizeof(char *))
12431171Sbrian
12531272Sbrianstruct pppThroughput throughput;
12631272Sbrian
12731272Sbrianvoid
12831272SbrianIpcpAddInOctets(int n)
1296059Samurai{
13031272Sbrian  throughput_addin(&throughput, n);
1316059Samurai}
1326059Samurai
13331272Sbrianvoid
13431272SbrianIpcpAddOutOctets(int n)
1356059Samurai{
13631272Sbrian  throughput_addout(&throughput, n);
1376059Samurai}
1386059Samurai
13925630Sbrianint
14031343SbrianReportIpcpStatus(struct cmdargs const *arg)
1416059Samurai{
1426059Samurai  struct ipcpstate *icp = &IpcpInfo;
1436059Samurai  struct fsm *fp = &IpcpFsm;
1446059Samurai
14526516Sbrian  if (!VarTerm)
14626516Sbrian    return 1;
14726516Sbrian  fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
14831514Sbrian  fprintf(VarTerm, " his side: %s, %s\n",
14931514Sbrian	  inet_ntoa(icp->his_ipaddr), vj2asc(icp->his_compproto));
15031514Sbrian  fprintf(VarTerm, " my  side: %s, %s\n",
15131514Sbrian	  inet_ntoa(icp->want_ipaddr), vj2asc(icp->want_compproto));
15229048Sbrian
15326516Sbrian  fprintf(VarTerm, "Defaults:\n");
15426516Sbrian  fprintf(VarTerm, " My Address:  %s/%d\n",
15528679Sbrian	  inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
15626516Sbrian  fprintf(VarTerm, " His Address: %s/%d\n",
15728679Sbrian	  inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
15828394Sbrian  if (HaveTriggerAddress)
15928679Sbrian    fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress));
16028394Sbrian  else
16128679Sbrian    fprintf(VarTerm, " Negotiation(trigger): MYADDR\n");
16226516Sbrian
16331272Sbrian  fprintf(VarTerm, "\n");
16431272Sbrian  throughput_disp(&throughput, VarTerm);
16531272Sbrian
16626516Sbrian  return 0;
1676059Samurai}
1686059Samurai
1696059Samuraivoid
1706059SamuraiIpcpDefAddress()
1716059Samurai{
1726059Samurai  struct hostent *hp;
1736059Samurai  char name[200];
1746059Samurai
17530715Sbrian  memset(&DefMyAddress, '\0', sizeof(DefMyAddress));
17630715Sbrian  memset(&DefHisAddress, '\0', sizeof(DefHisAddress));
17728394Sbrian  TriggerAddress.s_addr = 0;
17828394Sbrian  HaveTriggerAddress = 0;
1796059Samurai  if (gethostname(name, sizeof(name)) == 0) {
18028679Sbrian    hp = gethostbyname(name);
18128679Sbrian    if (hp && hp->h_addrtype == AF_INET) {
18230715Sbrian      memcpy(&DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length);
18328679Sbrian    }
1846059Samurai  }
1856059Samurai}
1866059Samurai
1876059Samuraivoid
1886059SamuraiIpcpInit()
1896059Samurai{
1906059Samurai  struct ipcpstate *icp = &IpcpInfo;
1916059Samurai
1926059Samurai  FsmInit(&IpcpFsm);
19330715Sbrian  memset(icp, '\0', sizeof(struct ipcpstate));
19431121Sbrian  if ((mode & MODE_DEDICATED) && !GetLabel()) {
1956059Samurai    icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
1966059Samurai  } else {
1976059Samurai    icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
1986059Samurai    icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
1996059Samurai  }
2009440Samurai
2019440Samurai  /*
20229048Sbrian   * Some implementations of PPP require that we send a
20329048Sbrian   * *special* value as our address, even though the rfc specifies
20429048Sbrian   * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
2059440Samurai   */
20628394Sbrian  if (HaveTriggerAddress) {
20728394Sbrian    icp->want_ipaddr.s_addr = TriggerAddress.s_addr;
20828461Sbrian    LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress));
2099440Samurai  }
2106059Samurai  if (Enabled(ConfVjcomp))
21130500Sbrian    icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8) | 1;
2126059Samurai  else
2136059Samurai    icp->want_compproto = 0;
2146059Samurai  icp->heis1172 = 0;
2156059Samurai  IpcpFsm.maxconfig = 10;
21631272Sbrian  throughput_init(&throughput);
2176059Samurai}
2186059Samurai
2196059Samuraistatic void
22028679SbrianIpcpInitRestartCounter(struct fsm * fp)
2216059Samurai{
2226735Samurai  fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
2236059Samurai  fp->restart = 5;
2246059Samurai}
2256059Samurai
2266059Samuraistatic void
22728679SbrianIpcpSendConfigReq(struct fsm * fp)
2286059Samurai{
2296059Samurai  u_char *cp;
2306059Samurai  struct ipcpstate *icp = &IpcpInfo;
23131514Sbrian  struct lcp_opt o;
2326059Samurai
2336059Samurai  cp = ReqBuff;
23428461Sbrian  LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
23531514Sbrian  if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR)) {
23631514Sbrian    o.id = TY_IPADDR;
23731514Sbrian    o.len = 6;
23831514Sbrian    *(u_long *)o.data = icp->want_ipaddr.s_addr;
23931514Sbrian    cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id],
24031514Sbrian                     inet_ntoa(icp->want_ipaddr));
24131514Sbrian  }
24231514Sbrian
2436059Samurai  if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
24431514Sbrian    const char *args;
24531514Sbrian    o.id = TY_COMPPROTO;
24631514Sbrian    if (icp->heis1172) {
24731514Sbrian      o.len = 4;
24831514Sbrian      *(u_short *)o.data = htons(PROTO_VJCOMP);
24931514Sbrian      args = "";
25031514Sbrian    } else {
25131514Sbrian      o.len = 6;
25231514Sbrian      *(u_long *)o.data = htonl(icp->want_compproto);
25331514Sbrian      args = vj2asc(icp->want_compproto);
25431514Sbrian    }
25531514Sbrian    cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], args);
2566059Samurai  }
2576059Samurai  FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
2586059Samurai}
2596059Samurai
2606059Samuraistatic void
26128679SbrianIpcpSendTerminateReq(struct fsm * fp)
2626059Samurai{
2636059Samurai  /* XXX: No code yet */
2646059Samurai}
2656059Samurai
2666059Samuraistatic void
26728679SbrianIpcpSendTerminateAck(struct fsm * fp)
2686059Samurai{
26928461Sbrian  LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
2706059Samurai  FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2716059Samurai}
2726059Samurai
2736059Samuraistatic void
27428679SbrianIpcpLayerStart(struct fsm * fp)
2756059Samurai{
27628461Sbrian  LogPrintf(LogIPCP, "IpcpLayerStart.\n");
2776059Samurai}
2786059Samurai
2796059Samuraistatic void
28028679SbrianIpcpLayerFinish(struct fsm * fp)
2816059Samurai{
28228461Sbrian  LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
28326098Sbrian  reconnect(RECON_FALSE);
2846059Samurai  LcpClose();
2856059Samurai  NewPhase(PHASE_TERMINATE);
2866059Samurai}
2876059Samurai
2886059Samuraistatic void
28928679SbrianIpcpLayerDown(struct fsm * fp)
2906059Samurai{
29128461Sbrian  LogPrintf(LogIPCP, "IpcpLayerDown.\n");
29231272Sbrian  throughput_stop(&throughput);
29331272Sbrian  throughput_log(&throughput, LogIPCP, NULL);
2946059Samurai}
2956059Samurai
2966059Samurai/*
2976059Samurai *  Called when IPCP has reached to OPEN state
2986059Samurai */
2996059Samuraistatic void
30028679SbrianIpcpLayerUp(struct fsm * fp)
3016059Samurai{
3026059Samurai  char tbuff[100];
3036059Samurai
30425630Sbrian  Prompt();
30528461Sbrian  LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
30628679Sbrian  snprintf(tbuff, sizeof(tbuff), "myaddr = %s ",
30728679Sbrian	   inet_ntoa(IpcpInfo.want_ipaddr));
30830187Sbrian
30930187Sbrian  if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP)
31030187Sbrian    VjInit((IpcpInfo.his_compproto >> 8) & 255);
31130187Sbrian
31228461Sbrian  LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
31328679Sbrian	    tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
31425630Sbrian  if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask) < 0) {
31526516Sbrian    if (VarTerm)
31626516Sbrian      LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
31726516Sbrian    return;
31825630Sbrian  }
31931343Sbrian#ifndef NOALIAS
32027763Sbrian  if (mode & MODE_ALIAS)
32128679Sbrian    VarPacketAliasSetAddress(IpcpInfo.want_ipaddr);
32231343Sbrian#endif
3236059Samurai  OsLinkup();
32431272Sbrian  throughput_start(&throughput);
3256059Samurai  StartIdleTimer();
3266059Samurai}
3276059Samurai
3286059Samuraivoid
3296059SamuraiIpcpUp()
3306059Samurai{
3316059Samurai  FsmUp(&IpcpFsm);
33228461Sbrian  LogPrintf(LogIPCP, "IPCP Up event!!\n");
3336059Samurai}
3346059Samurai
3356059Samuraivoid
3366059SamuraiIpcpOpen()
3376059Samurai{
3386059Samurai  FsmOpen(&IpcpFsm);
3396059Samurai}
3406059Samurai
3416059Samuraistatic int
34228679SbrianAcceptableAddr(struct in_range * prange, struct in_addr ipaddr)
3436059Samurai{
34428974Sbrian  LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr));
34528974Sbrian  LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr));
34626516Sbrian  LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
34726516Sbrian  LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
34828679Sbrian		  mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
34925661Sbrian  return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
35028679Sbrian    (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
3516059Samurai}
3526059Samurai
3536059Samuraistatic void
35431034SbrianIpcpDecodeConfig(u_char * cp, int plen, int mode_type)
3556059Samurai{
3566735Samurai  int type, length;
3576059Samurai  u_long *lp, compproto;
3586059Samurai  struct compreq *pcomp;
35918752Sjkh  struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
3606059Samurai  char tbuff[100];
36121488Simp  char tbuff2[100];
3626059Samurai
3636059Samurai  ackp = AckBuff;
3646059Samurai  nakp = NakBuff;
3656059Samurai  rejp = RejBuff;
3666059Samurai
3676059Samurai  while (plen >= sizeof(struct fsmconfig)) {
3686059Samurai    type = *cp;
3696059Samurai    length = cp[1];
37031171Sbrian    if (type < NCFTYPES)
37121488Simp      snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length);
37231171Sbrian    else if (type > 128 && type < 128 + NCFTYPES128)
37331171Sbrian      snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes128[type], length);
3746059Samurai    else
37531171Sbrian      snprintf(tbuff, sizeof(tbuff), " ??? ");
3766059Samurai
3776059Samurai    switch (type) {
3786059Samurai    case TY_IPADDR:		/* RFC1332 */
37928679Sbrian      lp = (u_long *) (cp + 2);
3806059Samurai      ipaddr.s_addr = *lp;
38128461Sbrian      LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
3826059Samurai
38331034Sbrian      switch (mode_type) {
3846059Samurai      case MODE_REQ:
3856059Samurai	if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
38628679Sbrian	  /*
38728679Sbrian	   * If destination address is not acceptable, insist to use what we
38828679Sbrian	   * want to use.
38928679Sbrian	   */
39030715Sbrian	  memcpy(nakp, cp, 2);
39130715Sbrian	  memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length);
39228679Sbrian	  nakp += length;
39328679Sbrian	  break;
3946059Samurai	}
3956059Samurai	IpcpInfo.his_ipaddr = ipaddr;
39630715Sbrian	memcpy(ackp, cp, length);
3976059Samurai	ackp += length;
3986059Samurai	break;
3996059Samurai      case MODE_NAK:
4006059Samurai	if (AcceptableAddr(&DefMyAddress, ipaddr)) {
40128679Sbrian
40228679Sbrian	  /*
40328679Sbrian	   * Use address suggested by peer.
40428679Sbrian	   */
40528974Sbrian	  snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff,
40628974Sbrian		   inet_ntoa(IpcpInfo.want_ipaddr));
40728461Sbrian	  LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
4086059Samurai	  IpcpInfo.want_ipaddr = ipaddr;
4096059Samurai	}
4106059Samurai	break;
4116059Samurai      case MODE_REJ:
4126059Samurai	IpcpInfo.his_reject |= (1 << type);
4136059Samurai	break;
4146059Samurai      }
4156059Samurai      break;
4166059Samurai    case TY_COMPPROTO:
41728679Sbrian      lp = (u_long *) (cp + 2);
4186059Samurai      compproto = htonl(*lp);
41931514Sbrian      LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
4206059Samurai
42131034Sbrian      switch (mode_type) {
4226059Samurai      case MODE_REQ:
4236059Samurai	if (!Acceptable(ConfVjcomp)) {
42430715Sbrian	  memcpy(rejp, cp, length);
4256059Samurai	  rejp += length;
4266059Samurai	} else {
42728679Sbrian	  pcomp = (struct compreq *) (cp + 2);
4286059Samurai	  switch (length) {
42928679Sbrian	  case 4:		/* RFC1172 */
4306059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
43126940Sbrian	      LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
4326059Samurai	      IpcpInfo.heis1172 = 1;
4336059Samurai	      IpcpInfo.his_compproto = compproto;
43430715Sbrian	      memcpy(ackp, cp, length);
4356059Samurai	      ackp += length;
4366059Samurai	    } else {
43730715Sbrian	      memcpy(nakp, cp, 2);
4386059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
43930715Sbrian	      memcpy(nakp+2, &pcomp, 2);
4406059Samurai	      nakp += length;
4416059Samurai	    }
4426059Samurai	    break;
44328679Sbrian	  case 6:		/* RFC1332 */
4446059Samurai	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
44528679Sbrian		&& pcomp->slots < MAX_STATES && pcomp->slots > 2) {
4466059Samurai	      IpcpInfo.his_compproto = compproto;
4476059Samurai	      IpcpInfo.heis1172 = 0;
44830715Sbrian	      memcpy(ackp, cp, length);
4496059Samurai	      ackp += length;
4506059Samurai	    } else {
45130715Sbrian	      memcpy(nakp, cp, 2);
4526059Samurai	      pcomp->proto = htons(PROTO_VJCOMP);
4536059Samurai	      pcomp->slots = MAX_STATES - 1;
4546059Samurai	      pcomp->compcid = 0;
45530715Sbrian	      memcpy(nakp+2, &pcomp, sizeof(pcomp));
4566059Samurai	      nakp += length;
4576059Samurai	    }
4586059Samurai	    break;
4596059Samurai	  default:
46030715Sbrian	    memcpy(rejp, cp, length);
4616059Samurai	    rejp += length;
4626059Samurai	    break;
4636059Samurai	  }
4646059Samurai	}
4656059Samurai	break;
4666059Samurai      case MODE_NAK:
46728461Sbrian	LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
46828679Sbrian		  tbuff, IpcpInfo.want_compproto, compproto);
4696059Samurai	IpcpInfo.want_compproto = compproto;
4706059Samurai	break;
4716059Samurai      case MODE_REJ:
4726059Samurai	IpcpInfo.his_reject |= (1 << type);
4736059Samurai	break;
4746059Samurai      }
4756059Samurai      break;
47628679Sbrian    case TY_IPADDRS:		/* RFC1172 */
47728679Sbrian      lp = (u_long *) (cp + 2);
4786059Samurai      ipaddr.s_addr = *lp;
47928679Sbrian      lp = (u_long *) (cp + 6);
4806059Samurai      dstipaddr.s_addr = *lp;
48128974Sbrian      snprintf(tbuff2, sizeof(tbuff2), "%s %s,", tbuff, inet_ntoa(ipaddr));
48228974Sbrian      LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
4836059Samurai
48431034Sbrian      switch (mode_type) {
4856059Samurai      case MODE_REQ:
4866059Samurai	IpcpInfo.his_ipaddr = ipaddr;
4876059Samurai	IpcpInfo.want_ipaddr = dstipaddr;
48830715Sbrian	memcpy(ackp, cp, length);
4896059Samurai	ackp += length;
4906059Samurai	break;
4916059Samurai      case MODE_NAK:
49228974Sbrian        snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s", tbuff,
49328974Sbrian		 inet_ntoa(IpcpInfo.want_ipaddr));
49428974Sbrian	LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
4956059Samurai	IpcpInfo.want_ipaddr = ipaddr;
4966059Samurai	IpcpInfo.his_ipaddr = dstipaddr;
4976059Samurai	break;
4986059Samurai      case MODE_REJ:
4996059Samurai	IpcpInfo.his_reject |= (1 << type);
5006059Samurai	break;
5016059Samurai      }
5026059Samurai      break;
50318752Sjkh
50428679Sbrian      /*
50528679Sbrian       * MS extensions for MS's PPP
50628679Sbrian       */
50718752Sjkh
50826516Sbrian#ifndef NOMSEXT
50928679Sbrian    case TY_PRIMARY_DNS:	/* MS PPP DNS negotiation hack */
51018752Sjkh    case TY_SECONDARY_DNS:
51128679Sbrian      if (!Enabled(ConfMSExt)) {
51228461Sbrian	LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
51328679Sbrian	IpcpInfo.my_reject |= (1 << type);
51430715Sbrian	memcpy(rejp, cp, length);
51518752Sjkh	rejp += length;
51618752Sjkh	break;
51718752Sjkh      }
51831034Sbrian      switch (mode_type) {
51918752Sjkh      case MODE_REQ:
52028679Sbrian	lp = (u_long *) (cp + 2);
52118752Sjkh	dnsstuff.s_addr = *lp;
52228679Sbrian	ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS) ? 1 : 0)].s_addr;
52328679Sbrian	if (dnsstuff.s_addr != ms_info_req.s_addr) {
52428679Sbrian
52518752Sjkh	  /*
52628679Sbrian	   * So the client has got the DNS stuff wrong (first request) so
52728974Sbrian	   * we'll tell 'em how it is
52828679Sbrian	   */
52930715Sbrian	  memcpy(nakp, cp, 2);	/* copy first two (type/length) */
53028679Sbrian	  LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n",
53128679Sbrian		    type,
53228679Sbrian		    inet_ntoa(dnsstuff),
53328679Sbrian		    inet_ntoa(ms_info_req));
53430715Sbrian	  memcpy(nakp+2, &ms_info_req, length);
53518752Sjkh	  nakp += length;
53618752Sjkh	  break;
53718752Sjkh	}
53828679Sbrian
53928679Sbrian	/*
54028679Sbrian	 * Otherwise they have it right (this time) so we send a ack packet
54128679Sbrian	 * back confirming it... end of story
54228679Sbrian	 */
54328679Sbrian	LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n",
54428679Sbrian		  type,
54528679Sbrian		  inet_ntoa(ms_info_req));
54630715Sbrian	memcpy(ackp, cp, length);
54718752Sjkh	ackp += length;
54818752Sjkh	break;
54928679Sbrian      case MODE_NAK:		/* what does this mean?? */
55028679Sbrian	LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type);
55118752Sjkh	break;
55228679Sbrian      case MODE_REJ:		/* confused?? me to :) */
55328679Sbrian	LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type);
55418752Sjkh	break;
55518752Sjkh      }
55618752Sjkh      break;
55718752Sjkh
55828679Sbrian    case TY_PRIMARY_NBNS:	/* MS PPP NetBIOS nameserver hack */
55918752Sjkh    case TY_SECONDARY_NBNS:
56028679Sbrian      if (!Enabled(ConfMSExt)) {
56128679Sbrian	LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n");
56228679Sbrian	IpcpInfo.my_reject |= (1 << type);
56330715Sbrian	memcpy(rejp, cp, length);
56428679Sbrian	rejp += length;
56528679Sbrian	break;
56628679Sbrian      }
56731034Sbrian      switch (mode_type) {
56818752Sjkh      case MODE_REQ:
56928679Sbrian	lp = (u_long *) (cp + 2);
57018752Sjkh	dnsstuff.s_addr = *lp;
57128679Sbrian	ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS) ? 1 : 0)].s_addr;
57228679Sbrian	if (dnsstuff.s_addr != ms_info_req.s_addr) {
57330715Sbrian	  memcpy(nakp, cp, 2);
57430715Sbrian	  memcpy(nakp+2, &ms_info_req.s_addr, length);
57528461Sbrian	  LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
57628679Sbrian		    type,
57728679Sbrian		    inet_ntoa(dnsstuff),
57828679Sbrian		    inet_ntoa(ms_info_req));
57918752Sjkh	  nakp += length;
58018752Sjkh	  break;
58118752Sjkh	}
58228461Sbrian	LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
58328679Sbrian		  type,
58428679Sbrian		  inet_ntoa(ms_info_req));
58530715Sbrian	memcpy(ackp, cp, length);
58618752Sjkh	ackp += length;
58718752Sjkh	break;
58818752Sjkh      case MODE_NAK:
58928679Sbrian	LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
59018752Sjkh	break;
59118752Sjkh      case MODE_REJ:
59228679Sbrian	LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
59318752Sjkh	break;
59418752Sjkh      }
59518752Sjkh      break;
59618752Sjkh
59726516Sbrian#endif
59818752Sjkh
5996059Samurai    default:
6006059Samurai      IpcpInfo.my_reject |= (1 << type);
60130715Sbrian      memcpy(rejp, cp, length);
6026059Samurai      rejp += length;
6036059Samurai      break;
6046059Samurai    }
6056059Samurai    plen -= length;
6066059Samurai    cp += length;
6076059Samurai  }
6086059Samurai}
6096059Samurai
6106059Samuraivoid
61128679SbrianIpcpInput(struct mbuf * bp)
6126059Samurai{
6136059Samurai  FsmInput(&IpcpFsm, bp);
6146059Samurai}
615