xref: /freebsd/usr.sbin/ppp/ipcp.c (revision 0640d357f29fb1c0daaaffadd0416c5981413afd)
1 /*
2  *	PPP IP Control Protocol (IPCP) Module
3  *
4  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5  *
6  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the Internet Initiative Japan, Inc.  The name of the
14  * IIJ may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * $Id: ipcp.c,v 1.67 1998/10/22 02:32:49 brian Exp $
21  *
22  *	TODO:
23  *		o More RFC1772 backward compatibility
24  */
25 #include <sys/param.h>
26 #include <netinet/in_systm.h>
27 #include <netinet/in.h>
28 #include <netinet/ip.h>
29 #include <arpa/inet.h>
30 #include <sys/socket.h>
31 #include <net/route.h>
32 #include <netdb.h>
33 #include <net/if.h>
34 #include <sys/sockio.h>
35 #include <sys/un.h>
36 #include <arpa/nameser.h>
37 
38 #include <fcntl.h>
39 #include <resolv.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/errno.h>
43 #include <termios.h>
44 #include <unistd.h>
45 
46 #ifndef NOALIAS
47 #ifdef __OpenBSD__
48 #include "alias.h"
49 #else
50 #include <alias.h>
51 #endif
52 #endif
53 #include "ua.h"
54 #include "defs.h"
55 #include "command.h"
56 #include "mbuf.h"
57 #include "log.h"
58 #include "timer.h"
59 #include "fsm.h"
60 #include "lcpproto.h"
61 #include "lcp.h"
62 #include "iplist.h"
63 #include "throughput.h"
64 #include "slcompress.h"
65 #include "lqr.h"
66 #include "hdlc.h"
67 #include "ipcp.h"
68 #include "filter.h"
69 #include "descriptor.h"
70 #include "vjcomp.h"
71 #include "async.h"
72 #include "ccp.h"
73 #include "link.h"
74 #include "physical.h"
75 #include "mp.h"
76 #include "bundle.h"
77 #include "id.h"
78 #include "arp.h"
79 #include "systems.h"
80 #include "prompt.h"
81 #include "route.h"
82 #include "iface.h"
83 
84 #undef REJECTED
85 #define	REJECTED(p, x)	((p)->peer_reject & (1<<(x)))
86 #define issep(ch) ((ch) == ' ' || (ch) == '\t')
87 #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
88 
89 struct compreq {
90   u_short proto;
91   u_char slots;
92   u_char compcid;
93 };
94 
95 static int IpcpLayerUp(struct fsm *);
96 static void IpcpLayerDown(struct fsm *);
97 static void IpcpLayerStart(struct fsm *);
98 static void IpcpLayerFinish(struct fsm *);
99 static void IpcpInitRestartCounter(struct fsm *);
100 static void IpcpSendConfigReq(struct fsm *);
101 static void IpcpSentTerminateReq(struct fsm *);
102 static void IpcpSendTerminateAck(struct fsm *, u_char);
103 static void IpcpDecodeConfig(struct fsm *, u_char *, int, int,
104                              struct fsm_decode *);
105 
106 static struct fsm_callbacks ipcp_Callbacks = {
107   IpcpLayerUp,
108   IpcpLayerDown,
109   IpcpLayerStart,
110   IpcpLayerFinish,
111   IpcpInitRestartCounter,
112   IpcpSendConfigReq,
113   IpcpSentTerminateReq,
114   IpcpSendTerminateAck,
115   IpcpDecodeConfig,
116   fsm_NullRecvResetReq,
117   fsm_NullRecvResetAck
118 };
119 
120 static const char *cftypes[] = {
121   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
122   "???",
123   "IPADDRS",	/* 1: IP-Addresses */	/* deprecated */
124   "COMPPROTO",	/* 2: IP-Compression-Protocol */
125   "IPADDR",	/* 3: IP-Address */
126 };
127 
128 #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
129 
130 static const char *cftypes128[] = {
131   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
132   "???",
133   "PRIDNS",	/* 129: Primary DNS Server Address */
134   "PRINBNS",	/* 130: Primary NBNS Server Address */
135   "SECDNS",	/* 131: Secondary DNS Server Address */
136   "SECNBNS",	/* 132: Secondary NBNS Server Address */
137 };
138 
139 #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0])
140 
141 void
142 ipcp_AddInOctets(struct ipcp *ipcp, int n)
143 {
144   throughput_addin(&ipcp->throughput, n);
145 }
146 
147 void
148 ipcp_AddOutOctets(struct ipcp *ipcp, int n)
149 {
150   throughput_addout(&ipcp->throughput, n);
151 }
152 
153 static void
154 getdns(struct ipcp *ipcp, struct in_addr addr[2])
155 {
156   FILE *fp;
157 
158   addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
159   if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
160     char buf[LINE_LEN], *cp, *end;
161     int n;
162 
163     n = 0;
164     buf[sizeof buf - 1] = '\0';
165     while (fgets(buf, sizeof buf - 1, fp)) {
166       if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) {
167         for (cp = buf + 11; issep(*cp); cp++)
168           ;
169         for (end = cp; isip(*end); end++)
170           ;
171         *end = '\0';
172         if (inet_aton(cp, addr+n) && ++n == 2)
173           break;
174       }
175     }
176     if (n == 1)
177       addr[1] = addr[0];
178     fclose(fp);
179   }
180 }
181 
182 static int
183 setdns(struct ipcp *ipcp, struct in_addr addr[2])
184 {
185   FILE *fp;
186   char wbuf[LINE_LEN + 54];
187   int wlen;
188 
189   if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) {
190     struct in_addr old[2];
191 
192     getdns(ipcp, old);
193     if (addr[0].s_addr == INADDR_ANY)
194       addr[0] = old[0];
195     if (addr[1].s_addr == INADDR_ANY)
196       addr[1] = old[1];
197   }
198 
199   if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) {
200     log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n",
201               _PATH_RESCONF);
202     return 0;
203   }
204 
205   wlen = 0;
206   if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
207     char buf[LINE_LEN];
208     int len;
209 
210     buf[sizeof buf - 1] = '\0';
211     while (fgets(buf, sizeof buf - 1, fp)) {
212       if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) {
213         len = strlen(buf);
214         if (len > sizeof wbuf - wlen) {
215           log_Printf(LogWARN, "%s: Can only cope with max file size %d\n",
216                     _PATH_RESCONF, LINE_LEN);
217           fclose(fp);
218           return 0;
219         }
220         memcpy(wbuf + wlen, buf, len);
221         wlen += len;
222       }
223     }
224     fclose(fp);
225   }
226 
227   if (addr[0].s_addr != INADDR_ANY) {
228     snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
229              inet_ntoa(addr[0]));
230     log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11);
231     wlen += strlen(wbuf + wlen);
232   }
233 
234   if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) {
235     snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
236              inet_ntoa(addr[1]));
237     log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11);
238     wlen += strlen(wbuf + wlen);
239   }
240 
241   if (wlen) {
242     int fd;
243 
244     if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) {
245       if (write(fd, wbuf, wlen) != wlen) {
246         log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno));
247         close(fd);
248         return 0;
249       }
250       if (ftruncate(fd, wlen) == -1) {
251         log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno));
252         close(fd);
253         return 0;
254       }
255       close(fd);
256     } else {
257       log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno));
258       return 0;
259     }
260   }
261 
262   return 1;
263 }
264 
265 int
266 ipcp_Show(struct cmdargs const *arg)
267 {
268   struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
269 
270   prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
271                 State2Nam(ipcp->fsm.state));
272   if (ipcp->fsm.state == ST_OPENED) {
273     prompt_Printf(arg->prompt, " His side:        %s, %s\n",
274 	          inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
275     prompt_Printf(arg->prompt, " My side:         %s, %s\n",
276 	          inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
277   }
278 
279   if (ipcp->route) {
280     prompt_Printf(arg->prompt, "\n");
281     route_ShowSticky(arg->prompt, ipcp->route);
282   }
283 
284   prompt_Printf(arg->prompt, "\nDefaults:\n");
285   prompt_Printf(arg->prompt, " My Address:      %s/%d",
286 	        inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width);
287 
288   if (ipcp->cfg.HaveTriggerAddress)
289     prompt_Printf(arg->prompt, " (trigger with %s)",
290                   inet_ntoa(ipcp->cfg.TriggerAddress));
291   prompt_Printf(arg->prompt, "\n VJ compression:  %s (%d slots %s slot "
292                 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg),
293                 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without");
294 
295   if (iplist_isvalid(&ipcp->cfg.peer_list))
296     prompt_Printf(arg->prompt, " His Address:     %s\n",
297                   ipcp->cfg.peer_list.src);
298   else
299     prompt_Printf(arg->prompt, " His Address:     %s/%d\n",
300 	          inet_ntoa(ipcp->cfg.peer_range.ipaddr),
301                   ipcp->cfg.peer_range.width);
302 
303   prompt_Printf(arg->prompt, " DNS:             %s, ",
304                 inet_ntoa(ipcp->cfg.ns.dns[0]));
305   prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]),
306                 command_ShowNegval(ipcp->cfg.ns.dns_neg));
307   prompt_Printf(arg->prompt, " NetBIOS NS:      %s, ",
308 	        inet_ntoa(ipcp->cfg.ns.nbns[0]));
309   prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1]));
310 
311   prompt_Printf(arg->prompt, "\n");
312   throughput_disp(&ipcp->throughput, arg->prompt);
313 
314   return 0;
315 }
316 
317 int
318 ipcp_vjset(struct cmdargs const *arg)
319 {
320   if (arg->argc != arg->argn+2)
321     return -1;
322   if (!strcasecmp(arg->argv[arg->argn], "slots")) {
323     int slots;
324 
325     slots = atoi(arg->argv[arg->argn+1]);
326     if (slots < 4 || slots > 16)
327       return 1;
328     arg->bundle->ncp.ipcp.cfg.vj.slots = slots;
329     return 0;
330   } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) {
331     if (!strcasecmp(arg->argv[arg->argn+1], "on"))
332       arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1;
333     else if (!strcasecmp(arg->argv[arg->argn+1], "off"))
334       arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0;
335     else
336       return 2;
337     return 0;
338   }
339   return -1;
340 }
341 
342 void
343 ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
344           const struct fsm_parent *parent)
345 {
346   struct hostent *hp;
347   char name[MAXHOSTNAMELEN];
348   static const char *timer_names[] =
349     {"IPCP restart", "IPCP openmode", "IPCP stopped"};
350 
351   fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP,
352            bundle, l, parent, &ipcp_Callbacks, timer_names);
353 
354   ipcp->route = NULL;
355   ipcp->cfg.vj.slots = DEF_VJ_STATES;
356   ipcp->cfg.vj.slotcomp = 1;
357   memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
358   if (gethostname(name, sizeof name) == 0) {
359     hp = gethostbyname(name);
360     if (hp && hp->h_addrtype == AF_INET)
361       memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
362   }
363   ipcp->cfg.netmask.s_addr = INADDR_ANY;
364   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
365   iplist_setsrc(&ipcp->cfg.peer_list, "");
366   ipcp->cfg.HaveTriggerAddress = 0;
367 
368   ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY;
369   ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY;
370   ipcp->cfg.ns.dns_neg = 0;
371   ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
372   ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
373 
374   ipcp->cfg.fsmretry = DEF_FSMRETRY;
375   ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED;
376 
377   memset(&ipcp->vj, '\0', sizeof ipcp->vj);
378 
379   throughput_init(&ipcp->throughput);
380   memset(ipcp->Queue, '\0', sizeof ipcp->Queue);
381   ipcp_Setup(ipcp);
382 }
383 
384 void
385 ipcp_SetLink(struct ipcp *ipcp, struct link *l)
386 {
387   ipcp->fsm.link = l;
388 }
389 
390 void
391 ipcp_Setup(struct ipcp *ipcp)
392 {
393   struct iface *iface = ipcp->fsm.bundle->iface;
394   int pos, n;
395 
396   ipcp->fsm.open_mode = 0;
397   ipcp->fsm.maxconfig = 10;
398 
399   if (iplist_isvalid(&ipcp->cfg.peer_list)) {
400     /* Try to give the peer a previously configured IP address */
401     for (n = 0; n < iface->in_addrs; n++) {
402       pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd);
403       if (pos != -1) {
404         ipcp->cfg.peer_range.ipaddr =
405           iplist_setcurpos(&ipcp->cfg.peer_list, pos);
406         break;
407       }
408     }
409     if (n == iface->in_addrs)
410       /* Ok, so none of 'em fit.... pick a random one */
411       ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
412 
413     ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
414     ipcp->cfg.peer_range.width = 32;
415   }
416 
417   ipcp->heis1172 = 0;
418 
419   ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr;
420   ipcp->peer_compproto = 0;
421 
422   if (ipcp->cfg.HaveTriggerAddress) {
423     /*
424      * Some implementations of PPP require that we send a
425      * *special* value as our address, even though the rfc specifies
426      * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
427      */
428     ipcp->my_ip = ipcp->cfg.TriggerAddress;
429     log_Printf(LogIPCP, "Using trigger address %s\n",
430               inet_ntoa(ipcp->cfg.TriggerAddress));
431   } else {
432     /*
433      * Otherwise, if we've used an IP number before and it's still within
434      * the network specified on the ``set ifaddr'' line, we really
435      * want to keep that IP number so that we can keep any existing
436      * connections that are bound to that IP (assuming we're not
437      * ``iface-alias''ing).
438      */
439     for (n = 0; n < iface->in_addrs; n++)
440       if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
441           (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) {
442         ipcp->my_ip = iface->in_addr[n].ifa;
443         break;
444       }
445     if (n == iface->in_addrs)
446       ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
447   }
448 
449   if (IsEnabled(ipcp->cfg.vj.neg))
450     ipcp->my_compproto = (PROTO_VJCOMP << 16) +
451                          ((ipcp->cfg.vj.slots - 1) << 8) +
452                          ipcp->cfg.vj.slotcomp;
453   else
454     ipcp->my_compproto = 0;
455   sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1);
456 
457   ipcp->peer_reject = 0;
458   ipcp->my_reject = 0;
459 }
460 
461 static int
462 ipcp_doproxyall(struct bundle *bundle,
463                 int (*proxyfun)(struct bundle *, struct in_addr, int), int s)
464 {
465   int n, ret;
466   struct sticky_route *rp;
467   struct in_addr addr;
468   struct ipcp *ipcp;
469 
470   ipcp = &bundle->ncp.ipcp;
471   for (rp = ipcp->route; rp != NULL; rp = rp->next) {
472     if (ntohl(rp->mask.s_addr) == INADDR_BROADCAST)
473         continue;
474     n = INADDR_BROADCAST - ntohl(rp->mask.s_addr) - 1;
475     if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) {
476       addr = rp->dst;
477       while (n--) {
478         addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
479 	log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr));
480 	ret = (*proxyfun)(bundle, addr, s);
481 	if (!ret)
482 	  return ret;
483       }
484     }
485   }
486 
487   return 0;
488 }
489 
490 static int
491 ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
492                   struct in_addr hisaddr, int silent)
493 {
494   static struct in_addr none = { INADDR_ANY };
495   struct in_addr mask, oaddr;
496   u_int32_t addr;
497 
498   addr = htonl(myaddr.s_addr);
499   if (IN_CLASSA(addr))
500     mask.s_addr = htonl(IN_CLASSA_NET);
501   else if (IN_CLASSB(addr))
502     mask.s_addr = htonl(IN_CLASSB_NET);
503   else
504     mask.s_addr = htonl(IN_CLASSC_NET);
505 
506   if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY &&
507       (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask.s_addr) == mask.s_addr)
508     mask.s_addr = htonl(bundle->ncp.ipcp.cfg.netmask.s_addr);
509 
510   oaddr.s_addr = bundle->iface->in_addrs ?
511                  bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY;
512   if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr,
513                  IFACE_ADD_FIRST|IFACE_FORCE_ADD))
514     return -1;
515 
516   if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1
517       && myaddr.s_addr != oaddr.s_addr)
518     /* Nuke the old one */
519     iface_inDelete(bundle->iface, oaddr);
520 
521   if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0)
522     bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0);
523 
524   if (Enabled(bundle, OPT_SROUTES))
525     route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr);
526 
527   if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) {
528     int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
529     if (s < 0)
530       log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n",
531                  strerror(errno));
532     else {
533       if (Enabled(bundle, OPT_PROXYALL))
534         ipcp_doproxyall(bundle, arp_SetProxy, s);
535       else if (Enabled(bundle, OPT_PROXY))
536         arp_SetProxy(bundle, hisaddr, s);
537       close(s);
538     }
539   }
540 
541   return 0;
542 }
543 
544 static struct in_addr
545 ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
546 {
547   struct in_addr try;
548   u_long f;
549 
550   for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) {
551     try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
552     log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n",
553               f, inet_ntoa(try));
554     if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) {
555       log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
556       break;
557     }
558   }
559 
560   if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) {
561     log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
562     try.s_addr = INADDR_ANY;
563   }
564 
565   return try;
566 }
567 
568 static void
569 IpcpInitRestartCounter(struct fsm * fp)
570 {
571   /* Set fsm timer load */
572   struct ipcp *ipcp = fsm2ipcp(fp);
573 
574   fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS;
575   fp->restart = DEF_REQs;
576 }
577 
578 static void
579 IpcpSendConfigReq(struct fsm *fp)
580 {
581   /* Send config REQ please */
582   struct physical *p = link2physical(fp->link);
583   struct ipcp *ipcp = fsm2ipcp(fp);
584   u_char buff[24];
585   struct lcp_opt *o;
586 
587   o = (struct lcp_opt *)buff;
588 
589   if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
590     memcpy(o->data, &ipcp->my_ip.s_addr, 4);
591     INC_LCP_OPT(TY_IPADDR, 6, o);
592   }
593 
594   if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
595     if (ipcp->heis1172) {
596       u_int16_t proto = PROTO_VJCOMP;
597 
598       ua_htons(&proto, o->data);
599       INC_LCP_OPT(TY_COMPPROTO, 4, o);
600     } else {
601       ua_htonl(&ipcp->my_compproto, o->data);
602       INC_LCP_OPT(TY_COMPPROTO, 6, o);
603     }
604   }
605 
606   if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
607       !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) &&
608       !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
609     struct in_addr dns[2];
610     getdns(ipcp, dns);
611     memcpy(o->data, &dns[0].s_addr, 4);
612     INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
613     memcpy(o->data, &dns[1].s_addr, 4);
614     INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
615   }
616 
617   fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff);
618 }
619 
620 static void
621 IpcpSentTerminateReq(struct fsm * fp)
622 {
623   /* Term REQ just sent by FSM */
624 }
625 
626 static void
627 IpcpSendTerminateAck(struct fsm *fp, u_char id)
628 {
629   /* Send Term ACK please */
630   fsm_Output(fp, CODE_TERMACK, id, NULL, 0);
631 }
632 
633 static void
634 IpcpLayerStart(struct fsm *fp)
635 {
636   /* We're about to start up ! */
637   struct ipcp *ipcp = fsm2ipcp(fp);
638 
639   log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name);
640   throughput_start(&ipcp->throughput, "IPCP throughput",
641                    Enabled(fp->bundle, OPT_THROUGHPUT));
642 
643   /* This is where we should be setting up the interface in AUTO mode */
644 }
645 
646 static void
647 IpcpLayerFinish(struct fsm *fp)
648 {
649   /* We're now down */
650   struct ipcp *ipcp = fsm2ipcp(fp);
651 
652   log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name);
653   throughput_stop(&ipcp->throughput);
654   throughput_log(&ipcp->throughput, LogIPCP, NULL);
655 }
656 
657 void
658 ipcp_CleanInterface(struct ipcp *ipcp)
659 {
660   struct iface *iface = ipcp->fsm.bundle->iface;
661 
662   route_Clean(ipcp->fsm.bundle, ipcp->route);
663 
664   if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) ||
665                           Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) {
666     int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
667     if (s < 0)
668       log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n",
669                  strerror(errno));
670     else {
671       if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL))
672         ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s);
673       else if (Enabled(ipcp->fsm.bundle, OPT_PROXY))
674         arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s);
675       close(s);
676     }
677   }
678 
679   iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL);
680 }
681 
682 static void
683 IpcpLayerDown(struct fsm *fp)
684 {
685   /* About to come down */
686   struct ipcp *ipcp = fsm2ipcp(fp);
687   const char *s;
688 
689   if (ipcp->fsm.bundle->iface->in_addrs)
690     s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa);
691   else
692     s = "Interface configuration error !";
693   log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s);
694 
695   /*
696    * XXX this stuff should really live in the FSM.  Our config should
697    * associate executable sections in files with events.
698    */
699   if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) {
700     if (bundle_GetLabel(fp->bundle)) {
701        if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
702                         LINKDOWNFILE, NULL, NULL) < 0)
703        system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
704     } else
705       system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
706   }
707 
708   ipcp_Setup(ipcp);
709 }
710 
711 int
712 ipcp_InterfaceUp(struct ipcp *ipcp)
713 {
714   if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) {
715     log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n");
716     return 0;
717   }
718 
719 #ifndef NOALIAS
720   if (ipcp->fsm.bundle->AliasEnabled)
721     PacketAliasSetAddress(ipcp->my_ip);
722 #endif
723 
724   return 1;
725 }
726 
727 static int
728 IpcpLayerUp(struct fsm *fp)
729 {
730   /* We're now up */
731   struct ipcp *ipcp = fsm2ipcp(fp);
732   char tbuff[16];
733 
734   log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
735   snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip));
736   log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n",
737              tbuff, inet_ntoa(ipcp->peer_ip));
738 
739   if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
740     sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
741 
742   if (!ipcp_InterfaceUp(ipcp))
743     return 0;
744 
745   /*
746    * XXX this stuff should really live in the FSM.  Our config should
747    * associate executable sections in files with events.
748    */
749   if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
750     if (bundle_GetLabel(fp->bundle)) {
751       if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
752                        LINKUPFILE, NULL, NULL) < 0)
753         system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
754     } else
755       system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
756   }
757 
758   log_DisplayPrompts();
759   return 1;
760 }
761 
762 static int
763 AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr)
764 {
765   /* Is the given IP in the given range ? */
766   return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
767     (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
768 }
769 
770 static void
771 IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
772                  struct fsm_decode *dec)
773 {
774   /* Deal with incoming PROTO_IPCP */
775   struct iface *iface = fp->bundle->iface;
776   struct ipcp *ipcp = fsm2ipcp(fp);
777   int type, length, gotdns, gotdnsnak, n;
778   u_int32_t compproto;
779   struct compreq *pcomp;
780   struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2];
781   char tbuff[100], tbuff2[100];
782 
783   gotdns = 0;
784   gotdnsnak = 0;
785   dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY;
786 
787   while (plen >= sizeof(struct fsmconfig)) {
788     type = *cp;
789     length = cp[1];
790 
791     if (length == 0) {
792       log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);
793       break;
794     }
795 
796     if (type < NCFTYPES)
797       snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length);
798     else if (type > 128 && type < 128 + NCFTYPES128)
799       snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length);
800     else
801       snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length);
802 
803     switch (type) {
804     case TY_IPADDR:		/* RFC1332 */
805       memcpy(&ipaddr.s_addr, cp + 2, 4);
806       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
807 
808       switch (mode_type) {
809       case MODE_REQ:
810         if (iplist_isvalid(&ipcp->cfg.peer_list)) {
811           if (ipaddr.s_addr == INADDR_ANY ||
812               iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 ||
813               ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr,
814                                 ipaddr, 1)) {
815             log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
816                       inet_ntoa(ipaddr));
817             /*
818              * If we've already had a valid address configured for the peer,
819              * try NAKing with that so that we don't have to upset things
820              * too much.
821              */
822             for (n = 0; n < iface->in_addrs; n++)
823               if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd)
824                   >=0) {
825                 ipcp->peer_ip = iface->in_addr[n].brd;
826                 break;
827               }
828 
829             if (n == iface->in_addrs)
830               /* Just pick an IP number from our list */
831               ipcp->peer_ip = ChooseHisAddr
832                 (fp->bundle, ipcp->cfg.my_range.ipaddr);
833 
834             if (ipcp->peer_ip.s_addr == INADDR_ANY) {
835 	      memcpy(dec->rejend, cp, length);
836 	      dec->rejend += length;
837             } else {
838 	      memcpy(dec->nakend, cp, 2);
839 	      memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
840 	      dec->nakend += length;
841             }
842 	    break;
843           }
844 	} else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) {
845 	  /*
846 	   * If destination address is not acceptable, NAK with what we
847 	   * want to use.
848 	   */
849 	  memcpy(dec->nakend, cp, 2);
850           for (n = 0; n < iface->in_addrs; n++)
851             if ((iface->in_addr[n].brd.s_addr &
852                  ipcp->cfg.peer_range.mask.s_addr)
853                 == (ipcp->cfg.peer_range.ipaddr.s_addr &
854                     ipcp->cfg.peer_range.mask.s_addr)) {
855               /* We prefer the already-configured address */
856 	      memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr,
857                      length - 2);
858               break;
859             }
860 
861           if (n == iface->in_addrs)
862 	    memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
863 
864 	  dec->nakend += length;
865 	  break;
866 	}
867 	ipcp->peer_ip = ipaddr;
868 	memcpy(dec->ackend, cp, length);
869 	dec->ackend += length;
870 	break;
871 
872       case MODE_NAK:
873 	if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
874 	  /* Use address suggested by peer */
875 	  snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
876 		   inet_ntoa(ipcp->my_ip));
877 	  log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
878 	  ipcp->my_ip = ipaddr;
879 	} else {
880 	  log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
881                     "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
882           fsm_Close(&ipcp->fsm);
883 	}
884 	break;
885 
886       case MODE_REJ:
887 	ipcp->peer_reject |= (1 << type);
888 	break;
889       }
890       break;
891 
892     case TY_COMPPROTO:
893       memcpy(&compproto, cp + 2, 4);
894       log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
895 
896       switch (mode_type) {
897       case MODE_REQ:
898 	if (!IsAccepted(ipcp->cfg.vj.neg)) {
899 	  memcpy(dec->rejend, cp, length);
900 	  dec->rejend += length;
901 	} else {
902 	  pcomp = (struct compreq *) (cp + 2);
903 	  switch (length) {
904 	  case 4:		/* RFC1172 */
905 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
906 	      log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
907 	      ipcp->heis1172 = 1;
908 	      ipcp->peer_compproto = compproto;
909 	      memcpy(dec->ackend, cp, length);
910 	      dec->ackend += length;
911 	    } else {
912 	      memcpy(dec->nakend, cp, 2);
913 	      pcomp->proto = htons(PROTO_VJCOMP);
914 	      memcpy(dec->nakend+2, &pcomp, 2);
915 	      dec->nakend += length;
916 	    }
917 	    break;
918 	  case 6:		/* RFC1332 */
919 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP
920 		&& pcomp->slots <= MAX_VJ_STATES
921                 && pcomp->slots >= MIN_VJ_STATES) {
922 	      ipcp->peer_compproto = compproto;
923 	      ipcp->heis1172 = 0;
924 	      memcpy(dec->ackend, cp, length);
925 	      dec->ackend += length;
926 	    } else {
927 	      memcpy(dec->nakend, cp, 2);
928 	      pcomp->proto = htons(PROTO_VJCOMP);
929 	      pcomp->slots = DEF_VJ_STATES;
930 	      pcomp->compcid = 0;
931 	      memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
932 	      dec->nakend += length;
933 	    }
934 	    break;
935 	  default:
936 	    memcpy(dec->rejend, cp, length);
937 	    dec->rejend += length;
938 	    break;
939 	  }
940 	}
941 	break;
942 
943       case MODE_NAK:
944 	log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
945 		  tbuff, ipcp->my_compproto, compproto);
946 	ipcp->my_compproto = compproto;
947 	break;
948 
949       case MODE_REJ:
950 	ipcp->peer_reject |= (1 << type);
951 	break;
952       }
953       break;
954 
955     case TY_IPADDRS:		/* RFC1172 */
956       memcpy(&ipaddr.s_addr, cp + 2, 4);
957       memcpy(&dstipaddr.s_addr, cp + 6, 4);
958       snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
959       log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
960 
961       switch (mode_type) {
962       case MODE_REQ:
963 	ipcp->peer_ip = ipaddr;
964 	ipcp->my_ip = dstipaddr;
965 	memcpy(dec->ackend, cp, length);
966 	dec->ackend += length;
967 	break;
968 
969       case MODE_NAK:
970         snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff,
971 		 inet_ntoa(ipcp->my_ip));
972 	log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
973 	ipcp->my_ip = ipaddr;
974 	ipcp->peer_ip = dstipaddr;
975 	break;
976 
977       case MODE_REJ:
978 	ipcp->peer_reject |= (1 << type);
979 	break;
980       }
981       break;
982 
983     case TY_PRIMARY_DNS:	/* DNS negotiation (rfc1877) */
984     case TY_SECONDARY_DNS:
985       memcpy(&ipaddr.s_addr, cp + 2, 4);
986       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
987 
988       switch (mode_type) {
989       case MODE_REQ:
990         if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
991           ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
992 	  memcpy(dec->rejend, cp, length);
993 	  dec->rejend += length;
994 	  break;
995         }
996         if (!gotdns) {
997           dns[0] = ipcp->cfg.ns.dns[0];
998           dns[1] = ipcp->cfg.ns.dns[1];
999           if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY)
1000             getdns(ipcp, dns);
1001           gotdns = 1;
1002         }
1003         have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1];
1004 
1005 	if (ipaddr.s_addr != have_ip.s_addr) {
1006 	  /*
1007 	   * The client has got the DNS stuff wrong (first request) so
1008 	   * we'll tell 'em how it is
1009 	   */
1010 	  memcpy(dec->nakend, cp, 2);	/* copy first two (type/length) */
1011 	  memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);
1012 	  dec->nakend += length;
1013 	} else {
1014 	  /*
1015 	   * Otherwise they have it right (this time) so we send a ack packet
1016 	   * back confirming it... end of story
1017 	   */
1018 	  memcpy(dec->ackend, cp, length);
1019 	  dec->ackend += length;
1020         }
1021 	break;
1022 
1023       case MODE_NAK:		/* what does this mean?? */
1024         if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
1025           gotdnsnak = 1;
1026           memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4);
1027 	}
1028 	break;
1029 
1030       case MODE_REJ:		/* Can't do much, stop asking */
1031         ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
1032 	break;
1033       }
1034       break;
1035 
1036     case TY_PRIMARY_NBNS:	/* M$ NetBIOS nameserver hack (rfc1877) */
1037     case TY_SECONDARY_NBNS:
1038       memcpy(&ipaddr.s_addr, cp + 2, 4);
1039       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1040 
1041       switch (mode_type) {
1042       case MODE_REQ:
1043 	have_ip.s_addr =
1044           ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
1045 
1046         if (have_ip.s_addr == INADDR_ANY) {
1047 	  log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
1048           ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
1049 	  memcpy(dec->rejend, cp, length);
1050 	  dec->rejend += length;
1051 	  break;
1052         }
1053 
1054 	if (ipaddr.s_addr != have_ip.s_addr) {
1055 	  memcpy(dec->nakend, cp, 2);
1056 	  memcpy(dec->nakend+2, &have_ip.s_addr, length);
1057 	  dec->nakend += length;
1058 	} else {
1059 	  memcpy(dec->ackend, cp, length);
1060 	  dec->ackend += length;
1061         }
1062 	break;
1063 
1064       case MODE_NAK:
1065 	log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
1066 	break;
1067 
1068       case MODE_REJ:
1069 	log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
1070 	break;
1071       }
1072       break;
1073 
1074     default:
1075       if (mode_type != MODE_NOP) {
1076         ipcp->my_reject |= (1 << type);
1077         memcpy(dec->rejend, cp, length);
1078         dec->rejend += length;
1079       }
1080       break;
1081     }
1082     plen -= length;
1083     cp += length;
1084   }
1085 
1086   if (gotdnsnak)
1087     if (!setdns(ipcp, dnsnak)) {
1088       ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
1089       ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
1090     }
1091 
1092   if (mode_type != MODE_NOP) {
1093     if (dec->rejend != dec->rej) {
1094       /* rejects are preferred */
1095       dec->ackend = dec->ack;
1096       dec->nakend = dec->nak;
1097     } else if (dec->nakend != dec->nak)
1098       /* then NAKs */
1099       dec->ackend = dec->ack;
1100   }
1101 }
1102 
1103 void
1104 ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp)
1105 {
1106   /* Got PROTO_IPCP from link */
1107   if (bundle_Phase(bundle) == PHASE_NETWORK)
1108     fsm_Input(&ipcp->fsm, bp);
1109   else {
1110     if (bundle_Phase(bundle) < PHASE_NETWORK)
1111       log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n",
1112                  ipcp->fsm.link->name, bundle_PhaseName(bundle));
1113     mbuf_Free(bp);
1114   }
1115 }
1116 
1117 int
1118 ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
1119 {
1120   struct ipcp *ipcp = &bundle->ncp.ipcp;
1121 
1122   /* Use `hisaddr' for the peers address (set iface if `setaddr') */
1123   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1124   iplist_reset(&ipcp->cfg.peer_list);
1125   if (strpbrk(hisaddr, ",-")) {
1126     iplist_setsrc(&ipcp->cfg.peer_list, hisaddr);
1127     if (iplist_isvalid(&ipcp->cfg.peer_list)) {
1128       iplist_setrandpos(&ipcp->cfg.peer_list);
1129       ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip);
1130       if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1131         log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
1132         return(0);
1133       }
1134       ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr;
1135       ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
1136       ipcp->cfg.peer_range.width = 32;
1137     } else {
1138       log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
1139       return 0;
1140     }
1141   } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr,
1142 		       &ipcp->cfg.peer_range.mask,
1143                        &ipcp->cfg.peer_range.width) != 0) {
1144     ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
1145 
1146     if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
1147                                      ipcp->cfg.peer_range.ipaddr, 0) < 0)
1148       return 0;
1149   } else
1150     return 0;
1151 
1152   return 1;
1153 }
1154