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