xref: /freebsd/usr.sbin/ppp/ipcp.c (revision 6140ba1177f35afccbaf1c04700fea5809d22ee7)
11ae349f5Scvs2svn /*
21ae349f5Scvs2svn  *	PPP IP Control Protocol (IPCP) Module
31ae349f5Scvs2svn  *
41ae349f5Scvs2svn  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
51ae349f5Scvs2svn  *
61ae349f5Scvs2svn  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
71ae349f5Scvs2svn  *
81ae349f5Scvs2svn  * Redistribution and use in source and binary forms are permitted
91ae349f5Scvs2svn  * provided that the above copyright notice and this paragraph are
101ae349f5Scvs2svn  * duplicated in all such forms and that any documentation,
111ae349f5Scvs2svn  * advertising materials, and other materials related to such
121ae349f5Scvs2svn  * distribution and use acknowledge that the software was developed
131ae349f5Scvs2svn  * by the Internet Initiative Japan, Inc.  The name of the
141ae349f5Scvs2svn  * IIJ may not be used to endorse or promote products derived
151ae349f5Scvs2svn  * from this software without specific prior written permission.
161ae349f5Scvs2svn  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
171ae349f5Scvs2svn  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
181ae349f5Scvs2svn  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
191ae349f5Scvs2svn  *
206140ba11SBrian Somers  * $Id: ipcp.c,v 1.50.2.6 1998/02/02 19:32:31 brian Exp $
211ae349f5Scvs2svn  *
221ae349f5Scvs2svn  *	TODO:
231ae349f5Scvs2svn  *		o More RFC1772 backwoard compatibility
241ae349f5Scvs2svn  */
251ae349f5Scvs2svn #include <sys/param.h>
261ae349f5Scvs2svn #include <netinet/in_systm.h>
271ae349f5Scvs2svn #include <netinet/in.h>
281ae349f5Scvs2svn #include <netinet/ip.h>
291ae349f5Scvs2svn #include <arpa/inet.h>
301ae349f5Scvs2svn #include <sys/socket.h>
311ae349f5Scvs2svn #include <netdb.h>
321ae349f5Scvs2svn 
331ae349f5Scvs2svn #include <stdio.h>
341ae349f5Scvs2svn #include <stdlib.h>
351ae349f5Scvs2svn #include <string.h>
366140ba11SBrian Somers #include <termios.h>
371ae349f5Scvs2svn #include <unistd.h>
381ae349f5Scvs2svn 
391ae349f5Scvs2svn #include "command.h"
401ae349f5Scvs2svn #include "mbuf.h"
411ae349f5Scvs2svn #include "log.h"
421ae349f5Scvs2svn #include "defs.h"
431ae349f5Scvs2svn #include "timer.h"
441ae349f5Scvs2svn #include "fsm.h"
451ae349f5Scvs2svn #include "lcpproto.h"
461ae349f5Scvs2svn #include "lcp.h"
471ae349f5Scvs2svn #include "iplist.h"
4829e275ceSBrian Somers #include "throughput.h"
491ae349f5Scvs2svn #include "ipcp.h"
501ae349f5Scvs2svn #include "slcompress.h"
517a6f8720SBrian Somers #include "bundle.h"
521ae349f5Scvs2svn #include "phase.h"
531ae349f5Scvs2svn #include "loadalias.h"
541ae349f5Scvs2svn #include "vars.h"
551ae349f5Scvs2svn #include "vjcomp.h"
561ae349f5Scvs2svn #include "ip.h"
571ae349f5Scvs2svn #include "route.h"
581ae349f5Scvs2svn #include "filter.h"
598c07a7b2SBrian Somers #include "hdlc.h"
606140ba11SBrian Somers #include "async.h"
618c07a7b2SBrian Somers #include "link.h"
6263b73463SBrian Somers #include "physical.h"
631ae349f5Scvs2svn 
6429e275ceSBrian Somers struct compreq {
6529e275ceSBrian Somers   u_short proto;
6629e275ceSBrian Somers   u_char slots;
6729e275ceSBrian Somers   u_char compcid;
6829e275ceSBrian Somers };
691ae349f5Scvs2svn 
701ae349f5Scvs2svn static void IpcpLayerUp(struct fsm *);
711ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *);
727308ec68SBrian Somers static void IpcpLayerStart(struct fsm *);
737308ec68SBrian Somers static void IpcpLayerFinish(struct fsm *);
741ae349f5Scvs2svn static void IpcpInitRestartCounter(struct fsm *);
757308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *);
767308ec68SBrian Somers static void IpcpSendTerminateReq(struct fsm *);
777308ec68SBrian Somers static void IpcpSendTerminateAck(struct fsm *);
787a6f8720SBrian Somers static void IpcpDecodeConfig(struct bundle *, u_char *, int, int);
791ae349f5Scvs2svn 
807308ec68SBrian Somers struct ipcpstate IpcpInfo = {
817308ec68SBrian Somers   {
821ae349f5Scvs2svn     "IPCP",
831ae349f5Scvs2svn     PROTO_IPCP,
841ae349f5Scvs2svn     IPCP_MAXCODE,
851ae349f5Scvs2svn     0,
861ae349f5Scvs2svn     ST_INITIAL,
871ae349f5Scvs2svn     0, 0, 0,
881ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* FSM timer */
891ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* Open timer */
901ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* Stopped timer */
911ae349f5Scvs2svn     LogIPCP,
927a6f8720SBrian Somers     NULL,				/* link */
937a6f8720SBrian Somers     NULL,				/* bundle */
941ae349f5Scvs2svn     IpcpLayerUp,
951ae349f5Scvs2svn     IpcpLayerDown,
961ae349f5Scvs2svn     IpcpLayerStart,
971ae349f5Scvs2svn     IpcpLayerFinish,
981ae349f5Scvs2svn     IpcpInitRestartCounter,
991ae349f5Scvs2svn     IpcpSendConfigReq,
1001ae349f5Scvs2svn     IpcpSendTerminateReq,
1011ae349f5Scvs2svn     IpcpSendTerminateAck,
1021ae349f5Scvs2svn     IpcpDecodeConfig,
1037308ec68SBrian Somers   },
1047308ec68SBrian Somers   MAX_VJ_STATES,
1057308ec68SBrian Somers   1
1061ae349f5Scvs2svn };
1071ae349f5Scvs2svn 
1081ae349f5Scvs2svn static const char *cftypes[] = {
1091ae349f5Scvs2svn   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
1101ae349f5Scvs2svn   "???",
1111ae349f5Scvs2svn   "IPADDRS",	/* 1: IP-Addresses */	/* deprecated */
1121ae349f5Scvs2svn   "COMPPROTO",	/* 2: IP-Compression-Protocol */
1131ae349f5Scvs2svn   "IPADDR",	/* 3: IP-Address */
1141ae349f5Scvs2svn };
1151ae349f5Scvs2svn 
1161ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
1171ae349f5Scvs2svn 
1181ae349f5Scvs2svn static const char *cftypes128[] = {
1191ae349f5Scvs2svn   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
1201ae349f5Scvs2svn   "???",
1211ae349f5Scvs2svn   "PRIDNS",	/* 129: Primary DNS Server Address */
1221ae349f5Scvs2svn   "PRINBNS",	/* 130: Primary NBNS Server Address */
1231ae349f5Scvs2svn   "SECDNS",	/* 131: Secondary DNS Server Address */
1241ae349f5Scvs2svn   "SECNBNS",	/* 132: Secondary NBNS Server Address */
1251ae349f5Scvs2svn };
1261ae349f5Scvs2svn 
1271ae349f5Scvs2svn #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0])
1281ae349f5Scvs2svn 
1291ae349f5Scvs2svn void
1301ae349f5Scvs2svn IpcpAddInOctets(int n)
1311ae349f5Scvs2svn {
13229e275ceSBrian Somers   throughput_addin(&IpcpInfo.throughput, n);
1331ae349f5Scvs2svn }
1341ae349f5Scvs2svn 
1351ae349f5Scvs2svn void
1361ae349f5Scvs2svn IpcpAddOutOctets(int n)
1371ae349f5Scvs2svn {
13829e275ceSBrian Somers   throughput_addout(&IpcpInfo.throughput, n);
1391ae349f5Scvs2svn }
1401ae349f5Scvs2svn 
1411ae349f5Scvs2svn int
1421ae349f5Scvs2svn ReportIpcpStatus(struct cmdargs const *arg)
1431ae349f5Scvs2svn {
1441ae349f5Scvs2svn   if (!VarTerm)
1451ae349f5Scvs2svn     return 1;
1467308ec68SBrian Somers   fprintf(VarTerm, "%s [%s]\n", IpcpInfo.fsm.name,
1477308ec68SBrian Somers           StateNames[IpcpInfo.fsm.state]);
1487308ec68SBrian Somers   if (IpcpInfo.fsm.state == ST_OPENED) {
14942e91bc7SBrian Somers     fprintf(VarTerm, " His side:               %s, %s\n",
1501ae349f5Scvs2svn 	    inet_ntoa(IpcpInfo.his_ipaddr), vj2asc(IpcpInfo.his_compproto));
15142e91bc7SBrian Somers     fprintf(VarTerm, " My side:                %s, %s\n",
1521ae349f5Scvs2svn 	    inet_ntoa(IpcpInfo.want_ipaddr), vj2asc(IpcpInfo.want_compproto));
1531ae349f5Scvs2svn   }
1541ae349f5Scvs2svn 
15542e91bc7SBrian Somers   fprintf(VarTerm, "\nDefaults:\n");
1561ae349f5Scvs2svn   fprintf(VarTerm, " My Address:             %s/%d\n",
15729e275ceSBrian Somers 	  inet_ntoa(IpcpInfo.DefMyAddress.ipaddr), IpcpInfo.DefMyAddress.width);
15829e275ceSBrian Somers   if (iplist_isvalid(&IpcpInfo.DefHisChoice))
15942e91bc7SBrian Somers     fprintf(VarTerm, " His Address:            %s\n",
16042e91bc7SBrian Somers             IpcpInfo.DefHisChoice.src);
1611ae349f5Scvs2svn   else
1621ae349f5Scvs2svn     fprintf(VarTerm, " His Address:            %s/%d\n",
16329e275ceSBrian Somers 	  inet_ntoa(IpcpInfo.DefHisAddress.ipaddr),
16429e275ceSBrian Somers           IpcpInfo.DefHisAddress.width);
16529e275ceSBrian Somers   if (IpcpInfo.HaveTriggerAddress)
16629e275ceSBrian Somers     fprintf(VarTerm, " Negotiation(trigger):   %s\n",
16729e275ceSBrian Somers             inet_ntoa(IpcpInfo.TriggerAddress));
1681ae349f5Scvs2svn   else
1691ae349f5Scvs2svn     fprintf(VarTerm, " Negotiation(trigger):   MYADDR\n");
17042e91bc7SBrian Somers   fprintf(VarTerm, " Initial VJ slots:       %d\n", IpcpInfo.VJInitSlots);
17142e91bc7SBrian Somers   fprintf(VarTerm, " Initial VJ compression: %s\n",
17242e91bc7SBrian Somers           IpcpInfo.VJInitComp ? "on" : "off");
1731ae349f5Scvs2svn 
1741ae349f5Scvs2svn   fprintf(VarTerm, "\n");
17529e275ceSBrian Somers   throughput_disp(&IpcpInfo.throughput, VarTerm);
1761ae349f5Scvs2svn 
1771ae349f5Scvs2svn   return 0;
1781ae349f5Scvs2svn }
1791ae349f5Scvs2svn 
1801ae349f5Scvs2svn void
1811ae349f5Scvs2svn IpcpDefAddress()
1821ae349f5Scvs2svn {
1837308ec68SBrian Somers   /* Setup default IP addresses (`hostname` -> 0.0.0.0) */
1841ae349f5Scvs2svn   struct hostent *hp;
1851ae349f5Scvs2svn   char name[200];
1861ae349f5Scvs2svn 
18729e275ceSBrian Somers   memset(&IpcpInfo.DefMyAddress, '\0', sizeof IpcpInfo.DefMyAddress);
18829e275ceSBrian Somers   memset(&IpcpInfo.DefHisAddress, '\0', sizeof IpcpInfo.DefHisAddress);
18929e275ceSBrian Somers   IpcpInfo.HaveTriggerAddress = 0;
1901ae349f5Scvs2svn   if (gethostname(name, sizeof name) == 0) {
1911ae349f5Scvs2svn     hp = gethostbyname(name);
19229e275ceSBrian Somers     if (hp && hp->h_addrtype == AF_INET)
19329e275ceSBrian Somers       memcpy(&IpcpInfo.DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length);
1941ae349f5Scvs2svn   }
1951ae349f5Scvs2svn }
1961ae349f5Scvs2svn 
1971ae349f5Scvs2svn int
1981ae349f5Scvs2svn SetInitVJ(struct cmdargs const *args)
1991ae349f5Scvs2svn {
2001ae349f5Scvs2svn   if (args->argc != 2)
2011ae349f5Scvs2svn     return -1;
2021ae349f5Scvs2svn   if (!strcasecmp(args->argv[0], "slots")) {
2031ae349f5Scvs2svn     int slots;
2041ae349f5Scvs2svn 
2051ae349f5Scvs2svn     slots = atoi(args->argv[1]);
2061ae349f5Scvs2svn     if (slots < 4 || slots > 16)
2071ae349f5Scvs2svn       return 1;
20829e275ceSBrian Somers     IpcpInfo.VJInitSlots = slots;
2091ae349f5Scvs2svn     return 0;
2101ae349f5Scvs2svn   } else if (!strcasecmp(args->argv[0], "slotcomp")) {
2111ae349f5Scvs2svn     if (!strcasecmp(args->argv[1], "on"))
21229e275ceSBrian Somers       IpcpInfo.VJInitComp = 1;
2131ae349f5Scvs2svn     else if (!strcasecmp(args->argv[1], "off"))
21429e275ceSBrian Somers       IpcpInfo.VJInitComp = 0;
2151ae349f5Scvs2svn     else
2161ae349f5Scvs2svn       return 2;
2171ae349f5Scvs2svn     return 0;
2181ae349f5Scvs2svn   }
2191ae349f5Scvs2svn   return -1;
2201ae349f5Scvs2svn }
2211ae349f5Scvs2svn 
2221ae349f5Scvs2svn void
2237a6f8720SBrian Somers IpcpInit(struct bundle *bundle, struct link *l)
2241ae349f5Scvs2svn {
2257308ec68SBrian Somers   /* Initialise ourselves */
2267a6f8720SBrian Somers   FsmInit(&IpcpInfo.fsm, bundle, l);
22729e275ceSBrian Somers   if (iplist_isvalid(&IpcpInfo.DefHisChoice))
22829e275ceSBrian Somers     iplist_setrandpos(&IpcpInfo.DefHisChoice);
22929e275ceSBrian Somers   IpcpInfo.his_compproto = 0;
23029e275ceSBrian Somers   IpcpInfo.his_reject = IpcpInfo.my_reject = 0;
23129e275ceSBrian Somers 
2321ae349f5Scvs2svn   if ((mode & MODE_DEDICATED) && !GetLabel()) {
23329e275ceSBrian Somers     IpcpInfo.want_ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr = INADDR_ANY;
23429e275ceSBrian Somers     IpcpInfo.his_ipaddr.s_addr = INADDR_ANY;
2351ae349f5Scvs2svn   } else {
23629e275ceSBrian Somers     IpcpInfo.want_ipaddr.s_addr = IpcpInfo.DefMyAddress.ipaddr.s_addr;
23729e275ceSBrian Somers     IpcpInfo.his_ipaddr.s_addr = IpcpInfo.DefHisAddress.ipaddr.s_addr;
2381ae349f5Scvs2svn   }
2391ae349f5Scvs2svn 
2401ae349f5Scvs2svn   /*
2411ae349f5Scvs2svn    * Some implementations of PPP require that we send a
2421ae349f5Scvs2svn    * *special* value as our address, even though the rfc specifies
2431ae349f5Scvs2svn    * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
2441ae349f5Scvs2svn    */
24529e275ceSBrian Somers   if (IpcpInfo.HaveTriggerAddress) {
24629e275ceSBrian Somers     IpcpInfo.want_ipaddr.s_addr = IpcpInfo.TriggerAddress.s_addr;
24729e275ceSBrian Somers     LogPrintf(LogIPCP, "Using trigger address %s\n",
24829e275ceSBrian Somers               inet_ntoa(IpcpInfo.TriggerAddress));
2491ae349f5Scvs2svn   }
25029e275ceSBrian Somers 
2511ae349f5Scvs2svn   if (Enabled(ConfVjcomp))
25229e275ceSBrian Somers     IpcpInfo.want_compproto = (PROTO_VJCOMP << 16) +
25329e275ceSBrian Somers                               ((IpcpInfo.VJInitSlots - 1) << 8) +
25429e275ceSBrian Somers                               IpcpInfo.VJInitComp;
2551ae349f5Scvs2svn   else
2561ae349f5Scvs2svn     IpcpInfo.want_compproto = 0;
2576140ba11SBrian Somers   VjInit(IpcpInfo.VJInitSlots - 1);
25829e275ceSBrian Somers 
2591ae349f5Scvs2svn   IpcpInfo.heis1172 = 0;
2607308ec68SBrian Somers   IpcpInfo.fsm.maxconfig = 10;
26129e275ceSBrian Somers   throughput_init(&IpcpInfo.throughput);
2621ae349f5Scvs2svn }
2631ae349f5Scvs2svn 
2641ae349f5Scvs2svn static void
2651ae349f5Scvs2svn IpcpInitRestartCounter(struct fsm * fp)
2661ae349f5Scvs2svn {
2677308ec68SBrian Somers   /* Set fsm timer load */
2681ae349f5Scvs2svn   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
2691ae349f5Scvs2svn   fp->restart = 5;
2701ae349f5Scvs2svn }
2711ae349f5Scvs2svn 
2721ae349f5Scvs2svn static void
2731ae349f5Scvs2svn IpcpSendConfigReq(struct fsm *fp)
2741ae349f5Scvs2svn {
2757308ec68SBrian Somers   /* Send config REQ please */
2768c07a7b2SBrian Somers   struct physical *p = link2physical(fp->link);
2771ae349f5Scvs2svn   u_char *cp;
2781ae349f5Scvs2svn   struct lcp_opt o;
2791ae349f5Scvs2svn 
2801ae349f5Scvs2svn   cp = ReqBuff;
2811ae349f5Scvs2svn   LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
2828c07a7b2SBrian Somers   if ((p && !Physical_IsSync(p)) || !REJECTED(&IpcpInfo, TY_IPADDR)) {
2831ae349f5Scvs2svn     o.id = TY_IPADDR;
2841ae349f5Scvs2svn     o.len = 6;
2851ae349f5Scvs2svn     *(u_long *)o.data = IpcpInfo.want_ipaddr.s_addr;
2861ae349f5Scvs2svn     cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id],
2871ae349f5Scvs2svn                      inet_ntoa(IpcpInfo.want_ipaddr));
2881ae349f5Scvs2svn   }
2891ae349f5Scvs2svn 
2901ae349f5Scvs2svn   if (IpcpInfo.want_compproto && !REJECTED(&IpcpInfo, TY_COMPPROTO)) {
2911ae349f5Scvs2svn     const char *args;
2921ae349f5Scvs2svn     o.id = TY_COMPPROTO;
2931ae349f5Scvs2svn     if (IpcpInfo.heis1172) {
2941ae349f5Scvs2svn       o.len = 4;
2951ae349f5Scvs2svn       *(u_short *)o.data = htons(PROTO_VJCOMP);
2961ae349f5Scvs2svn       args = "";
2971ae349f5Scvs2svn     } else {
2981ae349f5Scvs2svn       o.len = 6;
2991ae349f5Scvs2svn       *(u_long *)o.data = htonl(IpcpInfo.want_compproto);
3001ae349f5Scvs2svn       args = vj2asc(IpcpInfo.want_compproto);
3011ae349f5Scvs2svn     }
3021ae349f5Scvs2svn     cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], args);
3031ae349f5Scvs2svn   }
3041ae349f5Scvs2svn   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
3051ae349f5Scvs2svn }
3061ae349f5Scvs2svn 
3071ae349f5Scvs2svn static void
3081ae349f5Scvs2svn IpcpSendTerminateReq(struct fsm * fp)
3091ae349f5Scvs2svn {
3107308ec68SBrian Somers   /* Term REQ just sent by FSM */
3111ae349f5Scvs2svn }
3121ae349f5Scvs2svn 
3131ae349f5Scvs2svn static void
3141ae349f5Scvs2svn IpcpSendTerminateAck(struct fsm * fp)
3151ae349f5Scvs2svn {
3167308ec68SBrian Somers   /* Send Term ACK please */
3171ae349f5Scvs2svn   LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
3181ae349f5Scvs2svn   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
3191ae349f5Scvs2svn }
3201ae349f5Scvs2svn 
3211ae349f5Scvs2svn static void
3221ae349f5Scvs2svn IpcpLayerStart(struct fsm * fp)
3231ae349f5Scvs2svn {
3247308ec68SBrian Somers   /* We're about to start up ! */
3251ae349f5Scvs2svn   LogPrintf(LogIPCP, "IpcpLayerStart.\n");
3261ae349f5Scvs2svn }
3271ae349f5Scvs2svn 
3281ae349f5Scvs2svn static void
3291ae349f5Scvs2svn IpcpLayerFinish(struct fsm * fp)
3301ae349f5Scvs2svn {
3317308ec68SBrian Somers   /* We're now down */
3321ae349f5Scvs2svn   LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
3337308ec68SBrian Somers   /* Better tell LCP that it's all over (we're the only NCP) */
3341ae349f5Scvs2svn   reconnect(RECON_FALSE);
3357308ec68SBrian Somers   LcpClose(&LcpInfo.fsm);
3361ae349f5Scvs2svn }
3371ae349f5Scvs2svn 
3381ae349f5Scvs2svn static void
3391ae349f5Scvs2svn IpcpLayerDown(struct fsm * fp)
3401ae349f5Scvs2svn {
3417308ec68SBrian Somers   /* About to come down */
3421ae349f5Scvs2svn   LogPrintf(LogIPCP, "IpcpLayerDown.\n");
34329e275ceSBrian Somers   throughput_stop(&IpcpInfo.throughput);
34429e275ceSBrian Somers   throughput_log(&IpcpInfo.throughput, LogIPCP, NULL);
3451ae349f5Scvs2svn }
3461ae349f5Scvs2svn 
3471ae349f5Scvs2svn static void
3481ae349f5Scvs2svn IpcpLayerUp(struct fsm *fp)
3491ae349f5Scvs2svn {
3507308ec68SBrian Somers   /* We're now up */
3511ae349f5Scvs2svn   char tbuff[100];
3521ae349f5Scvs2svn 
3531ae349f5Scvs2svn   Prompt();
3541ae349f5Scvs2svn   LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
3551ae349f5Scvs2svn   snprintf(tbuff, sizeof tbuff, "myaddr = %s ",
3561ae349f5Scvs2svn 	   inet_ntoa(IpcpInfo.want_ipaddr));
3571ae349f5Scvs2svn 
3581ae349f5Scvs2svn   if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP)
3591ae349f5Scvs2svn     VjInit((IpcpInfo.his_compproto >> 8) & 255);
3601ae349f5Scvs2svn 
3611ae349f5Scvs2svn   LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
3621ae349f5Scvs2svn 	    tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
3637a6f8720SBrian Somers   if (bundle_SetIPaddress(fp->bundle, IpcpInfo.want_ipaddr,
3647a6f8720SBrian Somers                           IpcpInfo.his_ipaddr) < 0) {
3651ae349f5Scvs2svn     if (VarTerm)
3661ae349f5Scvs2svn       LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
3671ae349f5Scvs2svn     return;
3681ae349f5Scvs2svn   }
3691ae349f5Scvs2svn #ifndef NOALIAS
3701ae349f5Scvs2svn   if (mode & MODE_ALIAS)
3711ae349f5Scvs2svn     VarPacketAliasSetAddress(IpcpInfo.want_ipaddr);
3721ae349f5Scvs2svn #endif
3737a6f8720SBrian Somers   bundle_Linkup(fp->bundle);
37429e275ceSBrian Somers   throughput_start(&IpcpInfo.throughput);
3751ae349f5Scvs2svn   StartIdleTimer();
3761ae349f5Scvs2svn }
3771ae349f5Scvs2svn 
3781ae349f5Scvs2svn void
3791ae349f5Scvs2svn IpcpUp()
3801ae349f5Scvs2svn {
3817308ec68SBrian Somers   /* Lower layers are ready.... go */
3827308ec68SBrian Somers   FsmUp(&IpcpInfo.fsm);
3831ae349f5Scvs2svn   LogPrintf(LogIPCP, "IPCP Up event!!\n");
3841ae349f5Scvs2svn }
3851ae349f5Scvs2svn 
3861ae349f5Scvs2svn void
3877308ec68SBrian Somers IpcpDown()
3887308ec68SBrian Somers {
3897308ec68SBrian Somers   /* Physical link is gone - sudden death */
3907308ec68SBrian Somers   if (IpcpInfo.fsm.state >= ST_CLOSED) {
3917308ec68SBrian Somers     FsmDown(&IpcpInfo.fsm);
3927308ec68SBrian Somers     /* FsmDown() results in an IpcpLayerDown() if we're currently open. */
3937308ec68SBrian Somers     IpcpLayerFinish(&IpcpInfo.fsm);
3947308ec68SBrian Somers   }
3957308ec68SBrian Somers }
3967308ec68SBrian Somers 
3977308ec68SBrian Somers void
3981ae349f5Scvs2svn IpcpOpen()
3991ae349f5Scvs2svn {
4007308ec68SBrian Somers   /* Start IPCP please */
4017308ec68SBrian Somers   FsmOpen(&IpcpInfo.fsm);
4021ae349f5Scvs2svn }
4031ae349f5Scvs2svn 
4041ae349f5Scvs2svn static int
4051ae349f5Scvs2svn AcceptableAddr(struct in_range *prange, struct in_addr ipaddr)
4061ae349f5Scvs2svn {
4077308ec68SBrian Somers   /* Is the given IP in the given range ? */
4081ae349f5Scvs2svn   LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr));
4091ae349f5Scvs2svn   LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr));
4101ae349f5Scvs2svn   LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
4111ae349f5Scvs2svn   LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
4121ae349f5Scvs2svn 		  mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
4131ae349f5Scvs2svn   return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
4141ae349f5Scvs2svn     (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
4151ae349f5Scvs2svn }
4161ae349f5Scvs2svn 
4171ae349f5Scvs2svn static void
4187a6f8720SBrian Somers IpcpDecodeConfig(struct bundle *bundle, u_char * cp, int plen, int mode_type)
4191ae349f5Scvs2svn {
4207308ec68SBrian Somers   /* Deal with incoming PROTO_IPCP */
4211ae349f5Scvs2svn   int type, length;
4221ae349f5Scvs2svn   u_long *lp, compproto;
4231ae349f5Scvs2svn   struct compreq *pcomp;
4241ae349f5Scvs2svn   struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
4251ae349f5Scvs2svn   char tbuff[100];
4261ae349f5Scvs2svn   char tbuff2[100];
4271ae349f5Scvs2svn 
4281ae349f5Scvs2svn   ackp = AckBuff;
4291ae349f5Scvs2svn   nakp = NakBuff;
4301ae349f5Scvs2svn   rejp = RejBuff;
4311ae349f5Scvs2svn 
4321ae349f5Scvs2svn   while (plen >= sizeof(struct fsmconfig)) {
4331ae349f5Scvs2svn     type = *cp;
4341ae349f5Scvs2svn     length = cp[1];
4351ae349f5Scvs2svn     if (type < NCFTYPES)
4361ae349f5Scvs2svn       snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length);
4371ae349f5Scvs2svn     else if (type > 128 && type < 128 + NCFTYPES128)
4381ae349f5Scvs2svn       snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length);
4391ae349f5Scvs2svn     else
4401ae349f5Scvs2svn       snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length);
4411ae349f5Scvs2svn 
4421ae349f5Scvs2svn     switch (type) {
4431ae349f5Scvs2svn     case TY_IPADDR:		/* RFC1332 */
4441ae349f5Scvs2svn       lp = (u_long *) (cp + 2);
4451ae349f5Scvs2svn       ipaddr.s_addr = *lp;
4461ae349f5Scvs2svn       LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
4471ae349f5Scvs2svn 
4481ae349f5Scvs2svn       switch (mode_type) {
4491ae349f5Scvs2svn       case MODE_REQ:
45029e275ceSBrian Somers         if (iplist_isvalid(&IpcpInfo.DefHisChoice)) {
4511ae349f5Scvs2svn           if (ipaddr.s_addr == INADDR_ANY ||
45229e275ceSBrian Somers               iplist_ip2pos(&IpcpInfo.DefHisChoice, ipaddr) < 0 ||
4537a6f8720SBrian Somers               bundle_TrySetIPaddress(bundle, IpcpInfo.DefMyAddress.ipaddr,
4547a6f8720SBrian Somers                                      ipaddr)) {
4551ae349f5Scvs2svn             LogPrintf(LogIPCP, "%s: Address invalid or already in use\n",
4561ae349f5Scvs2svn                       inet_ntoa(ipaddr));
4577a6f8720SBrian Somers             IpcpInfo.his_ipaddr = ChooseHisAddr
4587a6f8720SBrian Somers               (bundle, IpcpInfo.DefMyAddress.ipaddr);
4591ae349f5Scvs2svn             if (IpcpInfo.his_ipaddr.s_addr == INADDR_ANY) {
4601ae349f5Scvs2svn 	      memcpy(rejp, cp, length);
4611ae349f5Scvs2svn 	      rejp += length;
4621ae349f5Scvs2svn             } else {
4631ae349f5Scvs2svn 	      memcpy(nakp, cp, 2);
4641ae349f5Scvs2svn 	      memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length - 2);
4651ae349f5Scvs2svn 	      nakp += length;
4661ae349f5Scvs2svn             }
4671ae349f5Scvs2svn 	    break;
4681ae349f5Scvs2svn           }
46929e275ceSBrian Somers 	} else if (!AcceptableAddr(&IpcpInfo.DefHisAddress, ipaddr)) {
4701ae349f5Scvs2svn 	  /*
4711ae349f5Scvs2svn 	   * If destination address is not acceptable, insist to use what we
4721ae349f5Scvs2svn 	   * want to use.
4731ae349f5Scvs2svn 	   */
4741ae349f5Scvs2svn 	  memcpy(nakp, cp, 2);
4751ae349f5Scvs2svn 	  memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length - 2);
4761ae349f5Scvs2svn 	  nakp += length;
4771ae349f5Scvs2svn 	  break;
4781ae349f5Scvs2svn 	}
4791ae349f5Scvs2svn 	IpcpInfo.his_ipaddr = ipaddr;
4801ae349f5Scvs2svn 	memcpy(ackp, cp, length);
4811ae349f5Scvs2svn 	ackp += length;
4821ae349f5Scvs2svn 	break;
4831ae349f5Scvs2svn       case MODE_NAK:
48429e275ceSBrian Somers 	if (AcceptableAddr(&IpcpInfo.DefMyAddress, ipaddr)) {
4851ae349f5Scvs2svn 	  /* Use address suggested by peer */
4861ae349f5Scvs2svn 	  snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
4871ae349f5Scvs2svn 		   inet_ntoa(IpcpInfo.want_ipaddr));
4881ae349f5Scvs2svn 	  LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
4891ae349f5Scvs2svn 	  IpcpInfo.want_ipaddr = ipaddr;
4901ae349f5Scvs2svn 	} else {
4911ae349f5Scvs2svn 	  LogPrintf(LogIPCP, "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
4927308ec68SBrian Somers           FsmClose(&IpcpInfo.fsm);
4931ae349f5Scvs2svn 	}
4941ae349f5Scvs2svn 	break;
4951ae349f5Scvs2svn       case MODE_REJ:
4961ae349f5Scvs2svn 	IpcpInfo.his_reject |= (1 << type);
4971ae349f5Scvs2svn 	break;
4981ae349f5Scvs2svn       }
4991ae349f5Scvs2svn       break;
5001ae349f5Scvs2svn     case TY_COMPPROTO:
5011ae349f5Scvs2svn       lp = (u_long *) (cp + 2);
5021ae349f5Scvs2svn       compproto = htonl(*lp);
5031ae349f5Scvs2svn       LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
5041ae349f5Scvs2svn 
5051ae349f5Scvs2svn       switch (mode_type) {
5061ae349f5Scvs2svn       case MODE_REQ:
5071ae349f5Scvs2svn 	if (!Acceptable(ConfVjcomp)) {
5081ae349f5Scvs2svn 	  memcpy(rejp, cp, length);
5091ae349f5Scvs2svn 	  rejp += length;
5101ae349f5Scvs2svn 	} else {
5111ae349f5Scvs2svn 	  pcomp = (struct compreq *) (cp + 2);
5121ae349f5Scvs2svn 	  switch (length) {
5131ae349f5Scvs2svn 	  case 4:		/* RFC1172 */
5141ae349f5Scvs2svn 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
5151ae349f5Scvs2svn 	      LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
5161ae349f5Scvs2svn 	      IpcpInfo.heis1172 = 1;
5171ae349f5Scvs2svn 	      IpcpInfo.his_compproto = compproto;
5181ae349f5Scvs2svn 	      memcpy(ackp, cp, length);
5191ae349f5Scvs2svn 	      ackp += length;
5201ae349f5Scvs2svn 	    } else {
5211ae349f5Scvs2svn 	      memcpy(nakp, cp, 2);
5221ae349f5Scvs2svn 	      pcomp->proto = htons(PROTO_VJCOMP);
5231ae349f5Scvs2svn 	      memcpy(nakp+2, &pcomp, 2);
5241ae349f5Scvs2svn 	      nakp += length;
5251ae349f5Scvs2svn 	    }
5261ae349f5Scvs2svn 	    break;
5271ae349f5Scvs2svn 	  case 6:		/* RFC1332 */
5281ae349f5Scvs2svn 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
52929e275ceSBrian Somers 		&& pcomp->slots < MAX_VJ_STATES && pcomp->slots > 2) {
5301ae349f5Scvs2svn 	      IpcpInfo.his_compproto = compproto;
5311ae349f5Scvs2svn 	      IpcpInfo.heis1172 = 0;
5321ae349f5Scvs2svn 	      memcpy(ackp, cp, length);
5331ae349f5Scvs2svn 	      ackp += length;
5341ae349f5Scvs2svn 	    } else {
5351ae349f5Scvs2svn 	      memcpy(nakp, cp, 2);
5361ae349f5Scvs2svn 	      pcomp->proto = htons(PROTO_VJCOMP);
53729e275ceSBrian Somers 	      pcomp->slots = MAX_VJ_STATES - 1;
5381ae349f5Scvs2svn 	      pcomp->compcid = 0;
5391ae349f5Scvs2svn 	      memcpy(nakp+2, &pcomp, sizeof pcomp);
5401ae349f5Scvs2svn 	      nakp += length;
5411ae349f5Scvs2svn 	    }
5421ae349f5Scvs2svn 	    break;
5431ae349f5Scvs2svn 	  default:
5441ae349f5Scvs2svn 	    memcpy(rejp, cp, length);
5451ae349f5Scvs2svn 	    rejp += length;
5461ae349f5Scvs2svn 	    break;
5471ae349f5Scvs2svn 	  }
5481ae349f5Scvs2svn 	}
5491ae349f5Scvs2svn 	break;
5501ae349f5Scvs2svn       case MODE_NAK:
5511ae349f5Scvs2svn 	LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
5521ae349f5Scvs2svn 		  tbuff, IpcpInfo.want_compproto, compproto);
5531ae349f5Scvs2svn 	IpcpInfo.want_compproto = compproto;
5541ae349f5Scvs2svn 	break;
5551ae349f5Scvs2svn       case MODE_REJ:
5561ae349f5Scvs2svn 	IpcpInfo.his_reject |= (1 << type);
5571ae349f5Scvs2svn 	break;
5581ae349f5Scvs2svn       }
5591ae349f5Scvs2svn       break;
5601ae349f5Scvs2svn     case TY_IPADDRS:		/* RFC1172 */
5611ae349f5Scvs2svn       lp = (u_long *) (cp + 2);
5621ae349f5Scvs2svn       ipaddr.s_addr = *lp;
5631ae349f5Scvs2svn       lp = (u_long *) (cp + 6);
5641ae349f5Scvs2svn       dstipaddr.s_addr = *lp;
5651ae349f5Scvs2svn       snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
5661ae349f5Scvs2svn       LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
5671ae349f5Scvs2svn 
5681ae349f5Scvs2svn       switch (mode_type) {
5691ae349f5Scvs2svn       case MODE_REQ:
5701ae349f5Scvs2svn 	IpcpInfo.his_ipaddr = ipaddr;
5711ae349f5Scvs2svn 	IpcpInfo.want_ipaddr = dstipaddr;
5721ae349f5Scvs2svn 	memcpy(ackp, cp, length);
5731ae349f5Scvs2svn 	ackp += length;
5741ae349f5Scvs2svn 	break;
5751ae349f5Scvs2svn       case MODE_NAK:
5761ae349f5Scvs2svn         snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff,
5771ae349f5Scvs2svn 		 inet_ntoa(IpcpInfo.want_ipaddr));
5781ae349f5Scvs2svn 	LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
5791ae349f5Scvs2svn 	IpcpInfo.want_ipaddr = ipaddr;
5801ae349f5Scvs2svn 	IpcpInfo.his_ipaddr = dstipaddr;
5811ae349f5Scvs2svn 	break;
5821ae349f5Scvs2svn       case MODE_REJ:
5831ae349f5Scvs2svn 	IpcpInfo.his_reject |= (1 << type);
5841ae349f5Scvs2svn 	break;
5851ae349f5Scvs2svn       }
5861ae349f5Scvs2svn       break;
5871ae349f5Scvs2svn 
5881ae349f5Scvs2svn       /*
5891ae349f5Scvs2svn        * MS extensions for MS's PPP
5901ae349f5Scvs2svn        */
5911ae349f5Scvs2svn 
5921ae349f5Scvs2svn #ifndef NOMSEXT
5931ae349f5Scvs2svn     case TY_PRIMARY_DNS:	/* MS PPP DNS negotiation hack */
5941ae349f5Scvs2svn     case TY_SECONDARY_DNS:
5951ae349f5Scvs2svn       if (!Enabled(ConfMSExt)) {
5961ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
5971ae349f5Scvs2svn 	IpcpInfo.my_reject |= (1 << type);
5981ae349f5Scvs2svn 	memcpy(rejp, cp, length);
5991ae349f5Scvs2svn 	rejp += length;
6001ae349f5Scvs2svn 	break;
6011ae349f5Scvs2svn       }
6021ae349f5Scvs2svn       switch (mode_type) {
6031ae349f5Scvs2svn       case MODE_REQ:
6041ae349f5Scvs2svn 	lp = (u_long *) (cp + 2);
6051ae349f5Scvs2svn 	dnsstuff.s_addr = *lp;
60629e275ceSBrian Somers 	ms_info_req.s_addr = IpcpInfo.ns_entries
60729e275ceSBrian Somers           [(type - TY_PRIMARY_DNS) ? 1 : 0].s_addr;
6081ae349f5Scvs2svn 	if (dnsstuff.s_addr != ms_info_req.s_addr) {
6091ae349f5Scvs2svn 
6101ae349f5Scvs2svn 	  /*
6111ae349f5Scvs2svn 	   * So the client has got the DNS stuff wrong (first request) so
6121ae349f5Scvs2svn 	   * we'll tell 'em how it is
6131ae349f5Scvs2svn 	   */
6141ae349f5Scvs2svn 	  memcpy(nakp, cp, 2);	/* copy first two (type/length) */
6151ae349f5Scvs2svn 	  LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n",
6161ae349f5Scvs2svn 		    type,
6171ae349f5Scvs2svn 		    inet_ntoa(dnsstuff),
6181ae349f5Scvs2svn 		    inet_ntoa(ms_info_req));
6191ae349f5Scvs2svn 	  memcpy(nakp+2, &ms_info_req, length);
6201ae349f5Scvs2svn 	  nakp += length;
6211ae349f5Scvs2svn 	  break;
6221ae349f5Scvs2svn 	}
6231ae349f5Scvs2svn 
6241ae349f5Scvs2svn 	/*
6251ae349f5Scvs2svn 	 * Otherwise they have it right (this time) so we send a ack packet
6261ae349f5Scvs2svn 	 * back confirming it... end of story
6271ae349f5Scvs2svn 	 */
6281ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n",
6291ae349f5Scvs2svn 		  type,
6301ae349f5Scvs2svn 		  inet_ntoa(ms_info_req));
6311ae349f5Scvs2svn 	memcpy(ackp, cp, length);
6321ae349f5Scvs2svn 	ackp += length;
6331ae349f5Scvs2svn 	break;
6341ae349f5Scvs2svn       case MODE_NAK:		/* what does this mean?? */
6351ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type);
6361ae349f5Scvs2svn 	break;
6371ae349f5Scvs2svn       case MODE_REJ:		/* confused?? me to :) */
6381ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type);
6391ae349f5Scvs2svn 	break;
6401ae349f5Scvs2svn       }
6411ae349f5Scvs2svn       break;
6421ae349f5Scvs2svn 
6431ae349f5Scvs2svn     case TY_PRIMARY_NBNS:	/* MS PPP NetBIOS nameserver hack */
6441ae349f5Scvs2svn     case TY_SECONDARY_NBNS:
6451ae349f5Scvs2svn       if (!Enabled(ConfMSExt)) {
6461ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n");
6471ae349f5Scvs2svn 	IpcpInfo.my_reject |= (1 << type);
6481ae349f5Scvs2svn 	memcpy(rejp, cp, length);
6491ae349f5Scvs2svn 	rejp += length;
6501ae349f5Scvs2svn 	break;
6511ae349f5Scvs2svn       }
6521ae349f5Scvs2svn       switch (mode_type) {
6531ae349f5Scvs2svn       case MODE_REQ:
6541ae349f5Scvs2svn 	lp = (u_long *) (cp + 2);
6551ae349f5Scvs2svn 	dnsstuff.s_addr = *lp;
65629e275ceSBrian Somers 	ms_info_req.s_addr = IpcpInfo.nbns_entries
65729e275ceSBrian Somers           [(type - TY_PRIMARY_NBNS) ? 1 : 0].s_addr;
6581ae349f5Scvs2svn 	if (dnsstuff.s_addr != ms_info_req.s_addr) {
6591ae349f5Scvs2svn 	  memcpy(nakp, cp, 2);
6601ae349f5Scvs2svn 	  memcpy(nakp+2, &ms_info_req.s_addr, length);
6611ae349f5Scvs2svn 	  LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
6621ae349f5Scvs2svn 		    type,
6631ae349f5Scvs2svn 		    inet_ntoa(dnsstuff),
6641ae349f5Scvs2svn 		    inet_ntoa(ms_info_req));
6651ae349f5Scvs2svn 	  nakp += length;
6661ae349f5Scvs2svn 	  break;
6671ae349f5Scvs2svn 	}
6681ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
6691ae349f5Scvs2svn 		  type,
6701ae349f5Scvs2svn 		  inet_ntoa(ms_info_req));
6711ae349f5Scvs2svn 	memcpy(ackp, cp, length);
6721ae349f5Scvs2svn 	ackp += length;
6731ae349f5Scvs2svn 	break;
6741ae349f5Scvs2svn       case MODE_NAK:
6751ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
6761ae349f5Scvs2svn 	break;
6771ae349f5Scvs2svn       case MODE_REJ:
6781ae349f5Scvs2svn 	LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
6791ae349f5Scvs2svn 	break;
6801ae349f5Scvs2svn       }
6811ae349f5Scvs2svn       break;
6821ae349f5Scvs2svn 
6831ae349f5Scvs2svn #endif
6841ae349f5Scvs2svn 
6851ae349f5Scvs2svn     default:
6861ae349f5Scvs2svn       IpcpInfo.my_reject |= (1 << type);
6871ae349f5Scvs2svn       memcpy(rejp, cp, length);
6881ae349f5Scvs2svn       rejp += length;
6891ae349f5Scvs2svn       break;
6901ae349f5Scvs2svn     }
6911ae349f5Scvs2svn     plen -= length;
6921ae349f5Scvs2svn     cp += length;
6931ae349f5Scvs2svn   }
6941ae349f5Scvs2svn }
6951ae349f5Scvs2svn 
6961ae349f5Scvs2svn void
6971ae349f5Scvs2svn IpcpInput(struct mbuf * bp)
6981ae349f5Scvs2svn {
6997308ec68SBrian Somers   /* Got PROTO_IPCP from link */
7007308ec68SBrian Somers   FsmInput(&IpcpInfo.fsm, bp);
7011ae349f5Scvs2svn }
7021ae349f5Scvs2svn 
7031ae349f5Scvs2svn int
7047a6f8720SBrian Somers UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
7051ae349f5Scvs2svn {
7067308ec68SBrian Somers   /* Use `hisaddr' for the peers address (set iface if `setaddr') */
70729e275ceSBrian Somers   memset(&IpcpInfo.DefHisAddress, '\0', sizeof IpcpInfo.DefHisAddress);
70829e275ceSBrian Somers   iplist_reset(&IpcpInfo.DefHisChoice);
7091ae349f5Scvs2svn   if (strpbrk(hisaddr, ",-")) {
71029e275ceSBrian Somers     iplist_setsrc(&IpcpInfo.DefHisChoice, hisaddr);
71129e275ceSBrian Somers     if (iplist_isvalid(&IpcpInfo.DefHisChoice)) {
71229e275ceSBrian Somers       iplist_setrandpos(&IpcpInfo.DefHisChoice);
7137a6f8720SBrian Somers       IpcpInfo.his_ipaddr = ChooseHisAddr(bundle, IpcpInfo.want_ipaddr);
7141ae349f5Scvs2svn       if (IpcpInfo.his_ipaddr.s_addr == INADDR_ANY) {
71529e275ceSBrian Somers         LogPrintf(LogWARN, "%s: None available !\n", IpcpInfo.DefHisChoice.src);
7161ae349f5Scvs2svn         return(0);
7171ae349f5Scvs2svn       }
71829e275ceSBrian Somers       IpcpInfo.DefHisAddress.ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr;
71929e275ceSBrian Somers       IpcpInfo.DefHisAddress.mask.s_addr = INADDR_BROADCAST;
72029e275ceSBrian Somers       IpcpInfo.DefHisAddress.width = 32;
7211ae349f5Scvs2svn     } else {
7221ae349f5Scvs2svn       LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr);
7231ae349f5Scvs2svn       return 0;
7241ae349f5Scvs2svn     }
72529e275ceSBrian Somers   } else if (ParseAddr(1, &hisaddr, &IpcpInfo.DefHisAddress.ipaddr,
72629e275ceSBrian Somers 		       &IpcpInfo.DefHisAddress.mask,
72729e275ceSBrian Somers                        &IpcpInfo.DefHisAddress.width) != 0) {
72829e275ceSBrian Somers     IpcpInfo.his_ipaddr.s_addr = IpcpInfo.DefHisAddress.ipaddr.s_addr;
7291ae349f5Scvs2svn 
7307a6f8720SBrian Somers     if (setaddr && bundle_SetIPaddress(bundle, IpcpInfo.DefMyAddress.ipaddr,
7317a6f8720SBrian Somers                                    IpcpInfo.DefHisAddress.ipaddr) < 0) {
73229e275ceSBrian Somers       IpcpInfo.DefMyAddress.ipaddr.s_addr = INADDR_ANY;
73329e275ceSBrian Somers       IpcpInfo.DefHisAddress.ipaddr.s_addr = INADDR_ANY;
7341ae349f5Scvs2svn       return 0;
7351ae349f5Scvs2svn     }
7361ae349f5Scvs2svn   } else
7371ae349f5Scvs2svn     return 0;
7381ae349f5Scvs2svn 
7391ae349f5Scvs2svn   return 1;
7401ae349f5Scvs2svn }
741