xref: /freebsd/usr.sbin/ppp/ipcp.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
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  * $FreeBSD$
21  *
22  *	TODO:
23  *		o Support IPADDRS properly
24  *		o Validate the length in IpcpDecodeConfig
25  */
26 #include <sys/param.h>
27 #include <netinet/in_systm.h>
28 #include <netinet/in.h>
29 #include <netinet/ip.h>
30 #include <arpa/inet.h>
31 #include <sys/socket.h>
32 #include <net/route.h>
33 #include <netdb.h>
34 #include <sys/un.h>
35 
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <resolv.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/stat.h>
42 #include <termios.h>
43 #include <unistd.h>
44 
45 #ifndef NONAT
46 #ifdef LOCALNAT
47 #include "alias.h"
48 #else
49 #include <alias.h>
50 #endif
51 #endif
52 
53 #include "layer.h"
54 #include "ua.h"
55 #include "defs.h"
56 #include "command.h"
57 #include "mbuf.h"
58 #include "log.h"
59 #include "timer.h"
60 #include "fsm.h"
61 #include "proto.h"
62 #include "lcp.h"
63 #include "iplist.h"
64 #include "throughput.h"
65 #include "slcompress.h"
66 #include "lqr.h"
67 #include "hdlc.h"
68 #include "ipcp.h"
69 #include "filter.h"
70 #include "descriptor.h"
71 #include "vjcomp.h"
72 #include "async.h"
73 #include "ccp.h"
74 #include "link.h"
75 #include "physical.h"
76 #include "mp.h"
77 #ifndef NORADIUS
78 #include "radius.h"
79 #endif
80 #include "bundle.h"
81 #include "id.h"
82 #include "arp.h"
83 #include "systems.h"
84 #include "prompt.h"
85 #include "route.h"
86 #include "iface.h"
87 #include "ip.h"
88 
89 #undef REJECTED
90 #define	REJECTED(p, x)	((p)->peer_reject & (1<<(x)))
91 #define issep(ch) ((ch) == ' ' || (ch) == '\t')
92 #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
93 
94 static u_short default_urgent_tcp_ports[] = {
95   21,	/* ftp */
96   22,	/* ssh */
97   23,	/* telnet */
98   513,	/* login */
99   514,	/* shell */
100   543,	/* klogin */
101   544	/* kshell */
102 };
103 
104 static u_short default_urgent_udp_ports[] = { };
105 
106 #define NDEFTCPPORTS \
107   (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0])
108 #define NDEFUDPPORTS \
109   (sizeof default_urgent_udp_ports / sizeof default_urgent_udp_ports[0])
110 
111 int
112 ipcp_IsUrgentPort(struct port_range *range, u_short src, u_short dst)
113 {
114   int f;
115 
116   for (f = 0; f < range->nports; f++)
117     if (range->port[f] == src || range->port[f] == dst)
118       return 1;
119 
120   return 0;
121 }
122 
123 void
124 ipcp_AddUrgentPort(struct port_range *range, u_short port)
125 {
126   u_short *newport;
127   int p;
128 
129   if (range->nports == range->maxports) {
130     range->maxports += 10;
131     newport = (u_short *)realloc(range->port,
132                                  range->maxports * sizeof(u_short));
133     if (newport == NULL) {
134       log_Printf(LogERROR, "ipcp_AddUrgentPort: realloc: %s\n",
135                  strerror(errno));
136       range->maxports -= 10;
137       return;
138     }
139     range->port = newport;
140   }
141 
142   for (p = 0; p < range->nports; p++)
143     if (range->port[p] == port) {
144       log_Printf(LogWARN, "%u: Port already set to urgent\n", port);
145       break;
146     } else if (range->port[p] > port) {
147       memmove(range->port + p + 1, range->port + p,
148               (range->nports - p) * sizeof(u_short));
149       range->port[p] = port;
150       range->nports++;
151       break;
152     }
153 
154   if (p == range->nports)
155     range->port[range->nports++] = port;
156 }
157 
158 void
159 ipcp_RemoveUrgentPort(struct port_range *range, u_short port)
160 {
161   int p;
162 
163   for (p = 0; p < range->nports; p++)
164     if (range->port[p] == port) {
165       if (p != range->nports - 1)
166         memmove(range->port + p, range->port + p + 1,
167                 (range->nports - p - 1) * sizeof(u_short));
168       range->nports--;
169       return;
170     }
171 
172   if (p == range->nports)
173     log_Printf(LogWARN, "%u: Port not set to urgent\n", port);
174 }
175 
176 void
177 ipcp_ClearUrgentPorts(struct port_range *range)
178 {
179   range->nports = 0;
180 }
181 
182 struct compreq {
183   u_short proto;
184   u_char slots;
185   u_char compcid;
186 };
187 
188 static int IpcpLayerUp(struct fsm *);
189 static void IpcpLayerDown(struct fsm *);
190 static void IpcpLayerStart(struct fsm *);
191 static void IpcpLayerFinish(struct fsm *);
192 static void IpcpInitRestartCounter(struct fsm *, int);
193 static void IpcpSendConfigReq(struct fsm *);
194 static void IpcpSentTerminateReq(struct fsm *);
195 static void IpcpSendTerminateAck(struct fsm *, u_char);
196 static void IpcpDecodeConfig(struct fsm *, u_char *, int, int,
197                              struct fsm_decode *);
198 
199 static struct fsm_callbacks ipcp_Callbacks = {
200   IpcpLayerUp,
201   IpcpLayerDown,
202   IpcpLayerStart,
203   IpcpLayerFinish,
204   IpcpInitRestartCounter,
205   IpcpSendConfigReq,
206   IpcpSentTerminateReq,
207   IpcpSendTerminateAck,
208   IpcpDecodeConfig,
209   fsm_NullRecvResetReq,
210   fsm_NullRecvResetAck
211 };
212 
213 static const char *
214 protoname(int proto)
215 {
216   static struct {
217     int id;
218     const char *txt;
219   } cftypes[] = {
220     /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
221     { 1, "IPADDRS" },		/* IP-Addresses */	/* deprecated */
222     { 2, "COMPPROTO" },		/* IP-Compression-Protocol */
223     { 3, "IPADDR" },		/* IP-Address */
224     { 129, "PRIDNS" },		/* 129: Primary DNS Server Address */
225     { 130, "PRINBNS" },		/* 130: Primary NBNS Server Address */
226     { 131, "SECDNS" },		/* 131: Secondary DNS Server Address */
227     { 132, "SECNBNS" }		/* 132: Secondary NBNS Server Address */
228   };
229   int f;
230 
231   for (f = 0; f < sizeof cftypes / sizeof *cftypes; f++)
232     if (cftypes[f].id == proto)
233       return cftypes[f].txt;
234 
235   return NumStr(proto, NULL, 0);
236 }
237 
238 void
239 ipcp_AddInOctets(struct ipcp *ipcp, int n)
240 {
241   throughput_addin(&ipcp->throughput, n);
242 }
243 
244 void
245 ipcp_AddOutOctets(struct ipcp *ipcp, int n)
246 {
247   throughput_addout(&ipcp->throughput, n);
248 }
249 
250 void
251 ipcp_LoadDNS(struct ipcp *ipcp)
252 {
253   int fd;
254 
255   ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE;
256 
257   if (ipcp->ns.resolv != NULL) {
258     free(ipcp->ns.resolv);
259     ipcp->ns.resolv = NULL;
260   }
261   if (ipcp->ns.resolv_nons != NULL) {
262     free(ipcp->ns.resolv_nons);
263     ipcp->ns.resolv_nons = NULL;
264   }
265   ipcp->ns.resolver = 0;
266 
267   if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) {
268     struct stat st;
269 
270     if (fstat(fd, &st) == 0) {
271       ssize_t got;
272 
273       if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL)
274         log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n",
275                    (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno));
276       else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) {
277         log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n",
278                    (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno));
279         free(ipcp->ns.resolv_nons);
280         ipcp->ns.resolv_nons = NULL;
281       } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) {
282         if (got == -1)
283           log_Printf(LogERROR, "Failed to read %s: %s\n",
284                      _PATH_RESCONF, strerror(errno));
285         else
286           log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n",
287                      _PATH_RESCONF, (unsigned long)got,
288                      (unsigned long)st.st_size);
289         free(ipcp->ns.resolv_nons);
290         ipcp->ns.resolv_nons = NULL;
291         free(ipcp->ns.resolv);
292         ipcp->ns.resolv = NULL;
293       } else {
294         char *cp, *cp_nons, *ncp, ch;
295         int n;
296 
297         ipcp->ns.resolv[st.st_size] = '\0';
298         ipcp->ns.resolver = 1;
299 
300         cp_nons = ipcp->ns.resolv_nons;
301         cp = ipcp->ns.resolv;
302         n = 0;
303 
304         while ((ncp = strstr(cp, "nameserver")) != NULL) {
305           if (ncp != cp) {
306             memcpy(cp_nons, cp, ncp - cp);
307             cp_nons += ncp - cp;
308           }
309           if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) {
310             memcpy(cp_nons, ncp, 9);
311             cp_nons += 9;
312             cp = ncp + 9;	/* Can't match "nameserver" at cp... */
313             continue;
314           }
315 
316           for (cp = ncp + 11; issep(*cp); cp++)	/* Skip whitespace */
317             ;
318 
319           for (ncp = cp; isip(*ncp); ncp++)		/* Jump over IP */
320             ;
321 
322           ch = *ncp;
323           *ncp = '\0';
324           if (n < 2 && inet_aton(cp, ipcp->ns.dns + n))
325             n++;
326           *ncp = ch;
327 
328           if ((cp = strchr(ncp, '\n')) == NULL)	/* Point at next line */
329             cp = ncp + strlen(ncp);
330           else
331             cp++;
332         }
333         strcpy(cp_nons, cp);	/* Copy the end - including the NUL */
334         cp_nons += strlen(cp_nons) - 1;
335         while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n')
336           *cp_nons-- = '\0';
337         if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) {
338           ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr;
339           ipcp->ns.dns[1].s_addr = INADDR_ANY;
340         }
341         bundle_AdjustDNS(ipcp->fsm.bundle, ipcp->ns.dns);
342       }
343     } else
344       log_Printf(LogERROR, "Failed to stat opened %s: %s\n",
345                  _PATH_RESCONF, strerror(errno));
346 
347     close(fd);
348   }
349 }
350 
351 int
352 ipcp_WriteDNS(struct ipcp *ipcp)
353 {
354   const char *paddr;
355   mode_t mask;
356   FILE *fp;
357 
358   if (ipcp->ns.dns[0].s_addr == INADDR_ANY &&
359       ipcp->ns.dns[1].s_addr == INADDR_ANY) {
360     log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n",
361               _PATH_RESCONF);
362     return 0;
363   }
364 
365   if (ipcp->ns.dns[0].s_addr == INADDR_ANY) {
366     ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr;
367     ipcp->ns.dns[1].s_addr = INADDR_ANY;
368   }
369 
370   mask = umask(0644);
371   if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) {
372     umask(mask);
373     fputs(ipcp->ns.resolv_nons, fp);
374     paddr = inet_ntoa(ipcp->ns.dns[0]);
375     log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr);
376     fprintf(fp, "\nnameserver %s\n", paddr);
377     if (ipcp->ns.dns[1].s_addr != INADDR_ANY &&
378         ipcp->ns.dns[1].s_addr != INADDR_NONE &&
379         ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) {
380       paddr = inet_ntoa(ipcp->ns.dns[1]);
381       log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr);
382       fprintf(fp, "nameserver %s\n", paddr);
383     }
384     if (fclose(fp) == EOF) {
385       log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF,
386                  strerror(errno));
387       return 0;
388     }
389   } else
390     umask(mask);
391 
392   return 1;
393 }
394 
395 void
396 ipcp_RestoreDNS(struct ipcp *ipcp)
397 {
398   if (ipcp->ns.resolver) {
399     ssize_t got;
400     size_t len;
401     int fd;
402 
403     if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) {
404       len = strlen(ipcp->ns.resolv);
405       if ((got = write(fd, ipcp->ns.resolv, len)) != len) {
406         if (got == -1)
407           log_Printf(LogERROR, "Failed rewriting %s: write: %s\n",
408                      _PATH_RESCONF, strerror(errno));
409         else
410           log_Printf(LogERROR, "Failed rewriting %s: wrote %lu of %lu\n",
411                      _PATH_RESCONF, (unsigned long)got, (unsigned long)len);
412       }
413       close(fd);
414     } else
415       log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF,
416                  strerror(errno));
417   } else if (remove(_PATH_RESCONF) == -1)
418     log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF,
419                strerror(errno));
420 
421 }
422 
423 int
424 ipcp_Show(struct cmdargs const *arg)
425 {
426   struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
427   int p;
428 
429   prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
430                 State2Nam(ipcp->fsm.state));
431   if (ipcp->fsm.state == ST_OPENED) {
432     prompt_Printf(arg->prompt, " His side:        %s, %s\n",
433 	          inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
434     prompt_Printf(arg->prompt, " My side:         %s, %s\n",
435 	          inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
436     prompt_Printf(arg->prompt, " Queued packets:  %lu\n",
437                   (unsigned long)ip_QueueLen(ipcp));
438   }
439 
440   if (ipcp->route) {
441     prompt_Printf(arg->prompt, "\n");
442     route_ShowSticky(arg->prompt, ipcp->route, "Sticky routes", 1);
443   }
444 
445   prompt_Printf(arg->prompt, "\nDefaults:\n");
446   prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config"
447                 " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout,
448                 ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s",
449                 ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s");
450   prompt_Printf(arg->prompt, " My Address:      %s/%d",
451 	        inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width);
452   prompt_Printf(arg->prompt, ", netmask %s\n", inet_ntoa(ipcp->cfg.netmask));
453   if (ipcp->cfg.HaveTriggerAddress)
454     prompt_Printf(arg->prompt, " Trigger address: %s\n",
455                   inet_ntoa(ipcp->cfg.TriggerAddress));
456 
457   prompt_Printf(arg->prompt, " VJ compression:  %s (%d slots %s slot "
458                 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg),
459                 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without");
460 
461   if (iplist_isvalid(&ipcp->cfg.peer_list))
462     prompt_Printf(arg->prompt, " His Address:     %s\n",
463                   ipcp->cfg.peer_list.src);
464   else
465     prompt_Printf(arg->prompt, " His Address:     %s/%d\n",
466 	          inet_ntoa(ipcp->cfg.peer_range.ipaddr),
467                   ipcp->cfg.peer_range.width);
468 
469   prompt_Printf(arg->prompt, " DNS:             %s",
470                 ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ?
471                 "none" : inet_ntoa(ipcp->cfg.ns.dns[0]));
472   if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE)
473     prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->cfg.ns.dns[1]));
474   prompt_Printf(arg->prompt, ", %s\n",
475                 command_ShowNegval(ipcp->cfg.ns.dns_neg));
476   prompt_Printf(arg->prompt, " Resolver DNS:    %s",
477                 ipcp->ns.dns[0].s_addr == INADDR_NONE ?
478                 "none" : inet_ntoa(ipcp->ns.dns[0]));
479   if (ipcp->ns.dns[1].s_addr != INADDR_NONE &&
480       ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr)
481     prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->ns.dns[1]));
482   prompt_Printf(arg->prompt, "\n NetBIOS NS:      %s, ",
483 	        inet_ntoa(ipcp->cfg.ns.nbns[0]));
484   prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1]));
485 
486   prompt_Printf(arg->prompt, " Urgent ports\n");
487   prompt_Printf(arg->prompt, "          TCP:    ");
488   if (ipcp->cfg.urgent.tcp.nports == 0)
489     prompt_Printf(arg->prompt, "none");
490   else
491     for (p = 0; p < ipcp->cfg.urgent.tcp.nports; p++) {
492       if (p)
493         prompt_Printf(arg->prompt, ", ");
494       prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.tcp.port[p]);
495     }
496   prompt_Printf(arg->prompt, "\n          UDP:    ");
497   if (ipcp->cfg.urgent.udp.nports == 0)
498     prompt_Printf(arg->prompt, "none");
499   else
500     for (p = 0; p < ipcp->cfg.urgent.udp.nports; p++) {
501       if (p)
502         prompt_Printf(arg->prompt, ", ");
503       prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.udp.port[p]);
504     }
505 
506   prompt_Printf(arg->prompt, "\n\n");
507   throughput_disp(&ipcp->throughput, arg->prompt);
508 
509   return 0;
510 }
511 
512 int
513 ipcp_vjset(struct cmdargs const *arg)
514 {
515   if (arg->argc != arg->argn+2)
516     return -1;
517   if (!strcasecmp(arg->argv[arg->argn], "slots")) {
518     int slots;
519 
520     slots = atoi(arg->argv[arg->argn+1]);
521     if (slots < 4 || slots > 16)
522       return 1;
523     arg->bundle->ncp.ipcp.cfg.vj.slots = slots;
524     return 0;
525   } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) {
526     if (!strcasecmp(arg->argv[arg->argn+1], "on"))
527       arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1;
528     else if (!strcasecmp(arg->argv[arg->argn+1], "off"))
529       arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0;
530     else
531       return 2;
532     return 0;
533   }
534   return -1;
535 }
536 
537 void
538 ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
539           const struct fsm_parent *parent)
540 {
541   struct hostent *hp;
542   char name[MAXHOSTNAMELEN];
543   static const char * const timer_names[] =
544     {"IPCP restart", "IPCP openmode", "IPCP stopped"};
545 
546   fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP,
547            bundle, l, parent, &ipcp_Callbacks, timer_names);
548 
549   ipcp->route = NULL;
550   ipcp->cfg.vj.slots = DEF_VJ_STATES;
551   ipcp->cfg.vj.slotcomp = 1;
552   memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
553   if (gethostname(name, sizeof name) == 0) {
554     hp = gethostbyname(name);
555     if (hp && hp->h_addrtype == AF_INET)
556       memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
557   }
558   ipcp->cfg.netmask.s_addr = INADDR_ANY;
559   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
560   iplist_setsrc(&ipcp->cfg.peer_list, "");
561   ipcp->cfg.HaveTriggerAddress = 0;
562 
563   ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE;
564   ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE;
565   ipcp->cfg.ns.dns_neg = 0;
566   ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
567   ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
568 
569   ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = NDEFTCPPORTS;
570   ipcp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short));
571   memcpy(ipcp->cfg.urgent.tcp.port, default_urgent_tcp_ports,
572          NDEFTCPPORTS * sizeof(u_short));
573 
574   ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = NDEFUDPPORTS;
575   ipcp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short));
576   memcpy(ipcp->cfg.urgent.udp.port, default_urgent_udp_ports,
577          NDEFUDPPORTS * sizeof(u_short));
578 
579   ipcp->cfg.fsm.timeout = DEF_FSMRETRY;
580   ipcp->cfg.fsm.maxreq = DEF_FSMTRIES;
581   ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
582   ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED;
583 
584   memset(&ipcp->vj, '\0', sizeof ipcp->vj);
585 
586   ipcp->ns.resolv = NULL;
587   ipcp->ns.resolv_nons = NULL;
588   ipcp->ns.writable = 1;
589   ipcp_LoadDNS(ipcp);
590 
591   throughput_init(&ipcp->throughput, SAMPLE_PERIOD);
592   memset(ipcp->Queue, '\0', sizeof ipcp->Queue);
593   ipcp_Setup(ipcp, INADDR_NONE);
594 }
595 
596 void
597 ipcp_Destroy(struct ipcp *ipcp)
598 {
599   if (ipcp->cfg.urgent.tcp.maxports) {
600     ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = 0;
601     free(ipcp->cfg.urgent.tcp.port);
602     ipcp->cfg.urgent.tcp.port = NULL;
603   }
604   if (ipcp->cfg.urgent.udp.maxports) {
605     ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = 0;
606     free(ipcp->cfg.urgent.udp.port);
607     ipcp->cfg.urgent.udp.port = NULL;
608   }
609   if (ipcp->ns.resolv != NULL) {
610     free(ipcp->ns.resolv);
611     ipcp->ns.resolv = NULL;
612   }
613   if (ipcp->ns.resolv_nons != NULL) {
614     free(ipcp->ns.resolv_nons);
615     ipcp->ns.resolv_nons = NULL;
616   }
617 }
618 
619 void
620 ipcp_SetLink(struct ipcp *ipcp, struct link *l)
621 {
622   ipcp->fsm.link = l;
623 }
624 
625 void
626 ipcp_Setup(struct ipcp *ipcp, u_int32_t mask)
627 {
628   struct iface *iface = ipcp->fsm.bundle->iface;
629   int pos, n;
630 
631   ipcp->fsm.open_mode = 0;
632   ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask;
633 
634   if (iplist_isvalid(&ipcp->cfg.peer_list)) {
635     /* Try to give the peer a previously configured IP address */
636     for (n = 0; n < iface->in_addrs; n++) {
637       pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd);
638       if (pos != -1) {
639         ipcp->cfg.peer_range.ipaddr =
640           iplist_setcurpos(&ipcp->cfg.peer_list, pos);
641         break;
642       }
643     }
644     if (n == iface->in_addrs)
645       /* Ok, so none of 'em fit.... pick a random one */
646       ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
647 
648     ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
649     ipcp->cfg.peer_range.width = 32;
650   }
651 
652   ipcp->heis1172 = 0;
653 
654   ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr;
655   ipcp->peer_compproto = 0;
656 
657   if (ipcp->cfg.HaveTriggerAddress) {
658     /*
659      * Some implementations of PPP require that we send a
660      * *special* value as our address, even though the rfc specifies
661      * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
662      */
663     ipcp->my_ip = ipcp->cfg.TriggerAddress;
664     log_Printf(LogIPCP, "Using trigger address %s\n",
665               inet_ntoa(ipcp->cfg.TriggerAddress));
666   } else {
667     /*
668      * Otherwise, if we've used an IP number before and it's still within
669      * the network specified on the ``set ifaddr'' line, we really
670      * want to keep that IP number so that we can keep any existing
671      * connections that are bound to that IP (assuming we're not
672      * ``iface-alias''ing).
673      */
674     for (n = 0; n < iface->in_addrs; n++)
675       if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
676           (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) {
677         ipcp->my_ip = iface->in_addr[n].ifa;
678         break;
679       }
680     if (n == iface->in_addrs)
681       ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
682   }
683 
684   if (IsEnabled(ipcp->cfg.vj.neg)
685 #ifndef NORADIUS
686       || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj)
687 #endif
688      )
689     ipcp->my_compproto = (PROTO_VJCOMP << 16) +
690                          ((ipcp->cfg.vj.slots - 1) << 8) +
691                          ipcp->cfg.vj.slotcomp;
692   else
693     ipcp->my_compproto = 0;
694   sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1);
695 
696   ipcp->peer_reject = 0;
697   ipcp->my_reject = 0;
698 
699   /* Copy startup values into ipcp->dns? */
700   if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE)
701     memcpy(ipcp->dns, ipcp->cfg.ns.dns, sizeof ipcp->dns);
702   else if (ipcp->ns.dns[0].s_addr != INADDR_NONE)
703     memcpy(ipcp->dns, ipcp->ns.dns, sizeof ipcp->dns);
704   else
705     ipcp->dns[0].s_addr = ipcp->dns[1].s_addr = INADDR_ANY;
706 
707   if (ipcp->dns[1].s_addr == INADDR_NONE)
708     ipcp->dns[1] = ipcp->dns[0];
709 }
710 
711 static int
712 ipcp_doproxyall(struct bundle *bundle,
713                 int (*proxyfun)(struct bundle *, struct in_addr, int), int s)
714 {
715   int n, ret;
716   struct sticky_route *rp;
717   struct in_addr addr;
718   struct ipcp *ipcp;
719 
720   ipcp = &bundle->ncp.ipcp;
721   for (rp = ipcp->route; rp != NULL; rp = rp->next) {
722     if (rp->mask.s_addr == INADDR_BROADCAST)
723         continue;
724     n = ntohl(INADDR_BROADCAST) - ntohl(rp->mask.s_addr) - 1;
725     if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) {
726       addr = rp->dst;
727       while (n--) {
728         addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
729 	log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr));
730 	ret = (*proxyfun)(bundle, addr, s);
731 	if (!ret)
732 	  return ret;
733       }
734     }
735   }
736 
737   return 0;
738 }
739 
740 static int
741 ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
742                   struct in_addr hisaddr, int silent)
743 {
744   struct in_addr mask, oaddr, none = { INADDR_ANY };
745 
746   mask = addr2mask(myaddr);
747 
748   if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY &&
749       (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr)
750     mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr;
751 
752   oaddr.s_addr = bundle->iface->in_addrs ?
753                  bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY;
754   if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr,
755                  IFACE_ADD_FIRST|IFACE_FORCE_ADD))
756     return -1;
757 
758   if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1
759       && myaddr.s_addr != oaddr.s_addr)
760     /* Nuke the old one */
761     iface_inDelete(bundle->iface, oaddr);
762 
763   if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0)
764     bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0);
765 
766   if (Enabled(bundle, OPT_SROUTES))
767     route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr,
768                  bundle->ncp.ipcp.ns.dns);
769 
770 #ifndef NORADIUS
771   if (bundle->radius.valid)
772     route_Change(bundle, bundle->radius.routes, myaddr, hisaddr,
773                  bundle->ncp.ipcp.ns.dns);
774 #endif
775 
776   if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) {
777     int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
778     if (s < 0)
779       log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n",
780                  strerror(errno));
781     else {
782       if (Enabled(bundle, OPT_PROXYALL))
783         ipcp_doproxyall(bundle, arp_SetProxy, s);
784       else if (Enabled(bundle, OPT_PROXY))
785         arp_SetProxy(bundle, hisaddr, s);
786       close(s);
787     }
788   }
789 
790   return 0;
791 }
792 
793 static struct in_addr
794 ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
795 {
796   struct in_addr try;
797   u_long f;
798 
799   for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) {
800     try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
801     log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n",
802               f, inet_ntoa(try));
803     if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) {
804       log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
805       break;
806     }
807   }
808 
809   if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) {
810     log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
811     try.s_addr = INADDR_ANY;
812   }
813 
814   return try;
815 }
816 
817 static void
818 IpcpInitRestartCounter(struct fsm *fp, int what)
819 {
820   /* Set fsm timer load */
821   struct ipcp *ipcp = fsm2ipcp(fp);
822 
823   fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS;
824   switch (what) {
825     case FSM_REQ_TIMER:
826       fp->restart = ipcp->cfg.fsm.maxreq;
827       break;
828     case FSM_TRM_TIMER:
829       fp->restart = ipcp->cfg.fsm.maxtrm;
830       break;
831     default:
832       fp->restart = 1;
833       break;
834   }
835 }
836 
837 static void
838 IpcpSendConfigReq(struct fsm *fp)
839 {
840   /* Send config REQ please */
841   struct physical *p = link2physical(fp->link);
842   struct ipcp *ipcp = fsm2ipcp(fp);
843   u_char buff[24];
844   struct lcp_opt *o;
845 
846   o = (struct lcp_opt *)buff;
847 
848   if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
849     memcpy(o->data, &ipcp->my_ip.s_addr, 4);
850     INC_LCP_OPT(TY_IPADDR, 6, o);
851   }
852 
853   if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
854     if (ipcp->heis1172) {
855       u_int16_t proto = PROTO_VJCOMP;
856 
857       ua_htons(&proto, o->data);
858       INC_LCP_OPT(TY_COMPPROTO, 4, o);
859     } else {
860       struct compreq req;
861 
862       req.proto = htons(ipcp->my_compproto >> 16);
863       req.slots = (ipcp->my_compproto >> 8) & 255;
864       req.compcid = ipcp->my_compproto & 1;
865       memcpy(o->data, &req, 4);
866       INC_LCP_OPT(TY_COMPPROTO, 6, o);
867     }
868   }
869 
870   if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
871       !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) &&
872       !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
873     memcpy(o->data, &ipcp->dns[0].s_addr, 4);
874     INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
875     memcpy(o->data, &ipcp->dns[1].s_addr, 4);
876     INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
877   }
878 
879   fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
880              MB_IPCPOUT);
881 }
882 
883 static void
884 IpcpSentTerminateReq(struct fsm *fp)
885 {
886   /* Term REQ just sent by FSM */
887 }
888 
889 static void
890 IpcpSendTerminateAck(struct fsm *fp, u_char id)
891 {
892   /* Send Term ACK please */
893   fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT);
894 }
895 
896 static void
897 IpcpLayerStart(struct fsm *fp)
898 {
899   /* We're about to start up ! */
900   struct ipcp *ipcp = fsm2ipcp(fp);
901 
902   log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name);
903   throughput_start(&ipcp->throughput, "IPCP throughput",
904                    Enabled(fp->bundle, OPT_THROUGHPUT));
905   fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3;
906 }
907 
908 static void
909 IpcpLayerFinish(struct fsm *fp)
910 {
911   /* We're now down */
912   struct ipcp *ipcp = fsm2ipcp(fp);
913 
914   log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name);
915   throughput_stop(&ipcp->throughput);
916   throughput_log(&ipcp->throughput, LogIPCP, NULL);
917 }
918 
919 void
920 ipcp_CleanInterface(struct ipcp *ipcp)
921 {
922   struct iface *iface = ipcp->fsm.bundle->iface;
923 
924   route_Clean(ipcp->fsm.bundle, ipcp->route);
925 
926   if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) ||
927                           Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) {
928     int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
929     if (s < 0)
930       log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n",
931                  strerror(errno));
932     else {
933       if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL))
934         ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s);
935       else if (Enabled(ipcp->fsm.bundle, OPT_PROXY))
936         arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s);
937       close(s);
938     }
939   }
940 
941   iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL);
942 }
943 
944 static void
945 IpcpLayerDown(struct fsm *fp)
946 {
947   /* About to come down */
948   static int recursing;
949   struct ipcp *ipcp = fsm2ipcp(fp);
950   const char *s;
951 
952   if (!recursing++) {
953     if (ipcp->fsm.bundle->iface->in_addrs)
954       s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa);
955     else
956       s = "Interface configuration error !";
957     log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s);
958 
959     /*
960      * XXX this stuff should really live in the FSM.  Our config should
961      * associate executable sections in files with events.
962      */
963     if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) {
964       if (bundle_GetLabel(fp->bundle)) {
965          if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
966                           LINKDOWNFILE, NULL, NULL) < 0)
967          system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
968       } else
969         system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
970     }
971 
972     ipcp_Setup(ipcp, INADDR_NONE);
973   }
974   recursing--;
975 }
976 
977 int
978 ipcp_InterfaceUp(struct ipcp *ipcp)
979 {
980   if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) {
981     log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n");
982     return 0;
983   }
984 
985 #ifndef NONAT
986   if (ipcp->fsm.bundle->NatEnabled)
987     PacketAliasSetAddress(ipcp->my_ip);
988 #endif
989 
990   return 1;
991 }
992 
993 static int
994 IpcpLayerUp(struct fsm *fp)
995 {
996   /* We're now up */
997   struct ipcp *ipcp = fsm2ipcp(fp);
998   char tbuff[16];
999 
1000   log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
1001   snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip));
1002   log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n",
1003              tbuff, inet_ntoa(ipcp->peer_ip));
1004 
1005   if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
1006     sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
1007 
1008   if (!ipcp_InterfaceUp(ipcp))
1009     return 0;
1010 
1011   /*
1012    * XXX this stuff should really live in the FSM.  Our config should
1013    * associate executable sections in files with events.
1014    */
1015   if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
1016     if (bundle_GetLabel(fp->bundle)) {
1017       if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
1018                        LINKUPFILE, NULL, NULL) < 0)
1019         system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
1020     } else
1021       system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
1022   }
1023 
1024   fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3;
1025   log_DisplayPrompts();
1026 
1027   return 1;
1028 }
1029 
1030 static int
1031 AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr)
1032 {
1033   /* Is the given IP in the given range ? */
1034   return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
1035     (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
1036 }
1037 
1038 static void
1039 IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
1040                  struct fsm_decode *dec)
1041 {
1042   /* Deal with incoming PROTO_IPCP */
1043   struct iface *iface = fp->bundle->iface;
1044   struct ipcp *ipcp = fsm2ipcp(fp);
1045   int type, length, gotdnsnak, n;
1046   u_int32_t compproto;
1047   struct compreq *pcomp;
1048   struct in_addr ipaddr, dstipaddr, have_ip;
1049   char tbuff[100], tbuff2[100];
1050 
1051   gotdnsnak = 0;
1052 
1053   while (plen >= sizeof(struct fsmconfig)) {
1054     type = *cp;
1055     length = cp[1];
1056 
1057     if (length == 0) {
1058       log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);
1059       break;
1060     }
1061 
1062     snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length);
1063 
1064     switch (type) {
1065     case TY_IPADDR:		/* RFC1332 */
1066       memcpy(&ipaddr.s_addr, cp + 2, 4);
1067       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1068 
1069       switch (mode_type) {
1070       case MODE_REQ:
1071         if (iplist_isvalid(&ipcp->cfg.peer_list)) {
1072           if (ipaddr.s_addr == INADDR_ANY ||
1073               iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 ||
1074               ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr,
1075                                 ipaddr, 1)) {
1076             log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
1077                       inet_ntoa(ipaddr));
1078             /*
1079              * If we've already had a valid address configured for the peer,
1080              * try NAKing with that so that we don't have to upset things
1081              * too much.
1082              */
1083             for (n = 0; n < iface->in_addrs; n++)
1084               if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd)
1085                   >=0) {
1086                 ipcp->peer_ip = iface->in_addr[n].brd;
1087                 break;
1088               }
1089 
1090             if (n == iface->in_addrs)
1091               /* Just pick an IP number from our list */
1092               ipcp->peer_ip = ChooseHisAddr
1093                 (fp->bundle, ipcp->cfg.my_range.ipaddr);
1094 
1095             if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1096 	      memcpy(dec->rejend, cp, length);
1097 	      dec->rejend += length;
1098             } else {
1099 	      memcpy(dec->nakend, cp, 2);
1100 	      memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
1101 	      dec->nakend += length;
1102             }
1103 	    break;
1104           }
1105 	} else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) {
1106 	  /*
1107 	   * If destination address is not acceptable, NAK with what we
1108 	   * want to use.
1109 	   */
1110 	  memcpy(dec->nakend, cp, 2);
1111           for (n = 0; n < iface->in_addrs; n++)
1112             if ((iface->in_addr[n].brd.s_addr &
1113                  ipcp->cfg.peer_range.mask.s_addr)
1114                 == (ipcp->cfg.peer_range.ipaddr.s_addr &
1115                     ipcp->cfg.peer_range.mask.s_addr)) {
1116               /* We prefer the already-configured address */
1117 	      memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr,
1118                      length - 2);
1119               break;
1120             }
1121 
1122           if (n == iface->in_addrs)
1123 	    memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
1124 
1125 	  dec->nakend += length;
1126 	  break;
1127 	}
1128 	ipcp->peer_ip = ipaddr;
1129 	memcpy(dec->ackend, cp, length);
1130 	dec->ackend += length;
1131 	break;
1132 
1133       case MODE_NAK:
1134 	if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
1135 	  /* Use address suggested by peer */
1136 	  snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
1137 		   inet_ntoa(ipcp->my_ip));
1138 	  log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
1139 	  ipcp->my_ip = ipaddr;
1140           bundle_AdjustFilters(fp->bundle, &ipcp->my_ip, NULL);
1141 	} else {
1142 	  log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
1143                     "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
1144           fsm_Close(&ipcp->fsm);
1145 	}
1146 	break;
1147 
1148       case MODE_REJ:
1149 	ipcp->peer_reject |= (1 << type);
1150 	break;
1151       }
1152       break;
1153 
1154     case TY_COMPPROTO:
1155       pcomp = (struct compreq *)(cp + 2);
1156       compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) +
1157                   pcomp->compcid;
1158       log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
1159 
1160       switch (mode_type) {
1161       case MODE_REQ:
1162 	if (!IsAccepted(ipcp->cfg.vj.neg)) {
1163 	  memcpy(dec->rejend, cp, length);
1164 	  dec->rejend += length;
1165 	} else {
1166 	  switch (length) {
1167 	  case 4:		/* RFC1172 */
1168 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
1169 	      log_Printf(LogWARN, "Peer is speaking RFC1172 compression "
1170                          "protocol !\n");
1171 	      ipcp->heis1172 = 1;
1172 	      ipcp->peer_compproto = compproto;
1173 	      memcpy(dec->ackend, cp, length);
1174 	      dec->ackend += length;
1175 	    } else {
1176 	      memcpy(dec->nakend, cp, 2);
1177 	      pcomp->proto = htons(PROTO_VJCOMP);
1178 	      memcpy(dec->nakend+2, &pcomp, 2);
1179 	      dec->nakend += length;
1180 	    }
1181 	    break;
1182 	  case 6:		/* RFC1332 */
1183 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
1184               if (pcomp->slots <= MAX_VJ_STATES
1185                   && pcomp->slots >= MIN_VJ_STATES) {
1186                 /* Ok, we can do that */
1187 	        ipcp->peer_compproto = compproto;
1188 	        ipcp->heis1172 = 0;
1189 	        memcpy(dec->ackend, cp, length);
1190 	        dec->ackend += length;
1191 	      } else {
1192                 /* Get as close as we can to what he wants */
1193 	        ipcp->heis1172 = 0;
1194 	        memcpy(dec->nakend, cp, 2);
1195 	        pcomp->slots = pcomp->slots < MIN_VJ_STATES ?
1196                                MIN_VJ_STATES : MAX_VJ_STATES;
1197 	        memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
1198 	        dec->nakend += length;
1199               }
1200 	    } else {
1201               /* What we really want */
1202 	      memcpy(dec->nakend, cp, 2);
1203 	      pcomp->proto = htons(PROTO_VJCOMP);
1204 	      pcomp->slots = DEF_VJ_STATES;
1205 	      pcomp->compcid = 1;
1206 	      memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
1207 	      dec->nakend += length;
1208 	    }
1209 	    break;
1210 	  default:
1211 	    memcpy(dec->rejend, cp, length);
1212 	    dec->rejend += length;
1213 	    break;
1214 	  }
1215 	}
1216 	break;
1217 
1218       case MODE_NAK:
1219 	if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
1220           if (pcomp->slots > MAX_VJ_STATES)
1221             pcomp->slots = MAX_VJ_STATES;
1222           else if (pcomp->slots < MIN_VJ_STATES)
1223             pcomp->slots = MIN_VJ_STATES;
1224           compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) +
1225                       pcomp->compcid;
1226         } else
1227           compproto = 0;
1228 	log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
1229 		  tbuff, ipcp->my_compproto, compproto);
1230         ipcp->my_compproto = compproto;
1231 	break;
1232 
1233       case MODE_REJ:
1234 	ipcp->peer_reject |= (1 << type);
1235 	break;
1236       }
1237       break;
1238 
1239     case TY_IPADDRS:		/* RFC1172 */
1240       memcpy(&ipaddr.s_addr, cp + 2, 4);
1241       memcpy(&dstipaddr.s_addr, cp + 6, 4);
1242       snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
1243       log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
1244 
1245       switch (mode_type) {
1246       case MODE_REQ:
1247 	memcpy(dec->rejend, cp, length);
1248 	dec->rejend += length;
1249 	break;
1250 
1251       case MODE_NAK:
1252       case MODE_REJ:
1253 	break;
1254       }
1255       break;
1256 
1257     case TY_PRIMARY_DNS:	/* DNS negotiation (rfc1877) */
1258     case TY_SECONDARY_DNS:
1259       memcpy(&ipaddr.s_addr, cp + 2, 4);
1260       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1261 
1262       switch (mode_type) {
1263       case MODE_REQ:
1264         if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
1265           ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
1266 	  memcpy(dec->rejend, cp, length);
1267 	  dec->rejend += length;
1268 	  break;
1269         }
1270         have_ip = ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1];
1271 
1272         if (type == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&
1273             ipaddr.s_addr == ipcp->dns[1].s_addr) {
1274           /* Swap 'em 'round */
1275           ipcp->dns[0] = ipcp->dns[1];
1276           ipcp->dns[1] = have_ip;
1277           have_ip = ipcp->dns[0];
1278         }
1279 
1280 	if (ipaddr.s_addr != have_ip.s_addr) {
1281 	  /*
1282 	   * The client has got the DNS stuff wrong (first request) so
1283 	   * we'll tell 'em how it is
1284 	   */
1285 	  memcpy(dec->nakend, cp, 2);	/* copy first two (type/length) */
1286 	  memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);
1287 	  dec->nakend += length;
1288 	} else {
1289 	  /*
1290 	   * Otherwise they have it right (this time) so we send a ack packet
1291 	   * back confirming it... end of story
1292 	   */
1293 	  memcpy(dec->ackend, cp, length);
1294 	  dec->ackend += length;
1295         }
1296 	break;
1297 
1298       case MODE_NAK:
1299         if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
1300           gotdnsnak = 1;
1301           memcpy(&ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4);
1302 	}
1303 	break;
1304 
1305       case MODE_REJ:		/* Can't do much, stop asking */
1306         ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
1307 	break;
1308       }
1309       break;
1310 
1311     case TY_PRIMARY_NBNS:	/* M$ NetBIOS nameserver hack (rfc1877) */
1312     case TY_SECONDARY_NBNS:
1313       memcpy(&ipaddr.s_addr, cp + 2, 4);
1314       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1315 
1316       switch (mode_type) {
1317       case MODE_REQ:
1318 	have_ip.s_addr =
1319           ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
1320 
1321         if (have_ip.s_addr == INADDR_ANY) {
1322 	  log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
1323           ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
1324 	  memcpy(dec->rejend, cp, length);
1325 	  dec->rejend += length;
1326 	  break;
1327         }
1328 
1329 	if (ipaddr.s_addr != have_ip.s_addr) {
1330 	  memcpy(dec->nakend, cp, 2);
1331 	  memcpy(dec->nakend+2, &have_ip.s_addr, length);
1332 	  dec->nakend += length;
1333 	} else {
1334 	  memcpy(dec->ackend, cp, length);
1335 	  dec->ackend += length;
1336         }
1337 	break;
1338 
1339       case MODE_NAK:
1340 	log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
1341 	break;
1342 
1343       case MODE_REJ:
1344 	log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
1345 	break;
1346       }
1347       break;
1348 
1349     default:
1350       if (mode_type != MODE_NOP) {
1351         ipcp->my_reject |= (1 << type);
1352         memcpy(dec->rejend, cp, length);
1353         dec->rejend += length;
1354       }
1355       break;
1356     }
1357     plen -= length;
1358     cp += length;
1359   }
1360 
1361   if (gotdnsnak) {
1362     memcpy(ipcp->ns.dns, ipcp->dns, sizeof ipcp->ns.dns);
1363     if (ipcp->ns.writable) {
1364       log_Printf(LogDEBUG, "Updating resolver\n");
1365       if (!ipcp_WriteDNS(ipcp)) {
1366         ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
1367         ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
1368       } else
1369         bundle_AdjustDNS(fp->bundle, ipcp->dns);
1370     } else {
1371       log_Printf(LogDEBUG, "Not updating resolver (readonly)\n");
1372       bundle_AdjustDNS(fp->bundle, ipcp->dns);
1373     }
1374   }
1375 
1376   if (mode_type != MODE_NOP) {
1377     if (dec->rejend != dec->rej) {
1378       /* rejects are preferred */
1379       dec->ackend = dec->ack;
1380       dec->nakend = dec->nak;
1381     } else if (dec->nakend != dec->nak)
1382       /* then NAKs */
1383       dec->ackend = dec->ack;
1384   }
1385 }
1386 
1387 extern struct mbuf *
1388 ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1389 {
1390   /* Got PROTO_IPCP from link */
1391   m_settype(bp, MB_IPCPIN);
1392   if (bundle_Phase(bundle) == PHASE_NETWORK)
1393     fsm_Input(&bundle->ncp.ipcp.fsm, bp);
1394   else {
1395     if (bundle_Phase(bundle) < PHASE_NETWORK)
1396       log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n",
1397                  l->name, bundle_PhaseName(bundle));
1398     m_freem(bp);
1399   }
1400   return NULL;
1401 }
1402 
1403 int
1404 ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr)
1405 {
1406   struct ipcp *ipcp = &bundle->ncp.ipcp;
1407 
1408   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1409   iplist_reset(&ipcp->cfg.peer_list);
1410   ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr = hisaddr;
1411   ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
1412   ipcp->cfg.peer_range.width = 32;
1413 
1414   if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0)
1415     return 0;
1416 
1417   return 1;	/* Ok */
1418 }
1419 
1420 int
1421 ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
1422 {
1423   struct ipcp *ipcp = &bundle->ncp.ipcp;
1424 
1425   /* Use `hisaddr' for the peers address (set iface if `setaddr') */
1426   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1427   iplist_reset(&ipcp->cfg.peer_list);
1428   if (strpbrk(hisaddr, ",-")) {
1429     iplist_setsrc(&ipcp->cfg.peer_list, hisaddr);
1430     if (iplist_isvalid(&ipcp->cfg.peer_list)) {
1431       iplist_setrandpos(&ipcp->cfg.peer_list);
1432       ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip);
1433       if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1434         log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
1435         return 0;
1436       }
1437       ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr;
1438       ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
1439       ipcp->cfg.peer_range.width = 32;
1440     } else {
1441       log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
1442       return 0;
1443     }
1444   } else if (ParseAddr(ipcp, hisaddr, &ipcp->cfg.peer_range.ipaddr,
1445 		       &ipcp->cfg.peer_range.mask,
1446                        &ipcp->cfg.peer_range.width) != 0) {
1447     ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
1448 
1449     if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
1450                                      ipcp->cfg.peer_range.ipaddr, 0) < 0)
1451       return 0;
1452   } else
1453     return 0;
1454 
1455   bundle_AdjustFilters(bundle, NULL, &ipcp->peer_ip);
1456 
1457   return 1;	/* Ok */
1458 }
1459 
1460 struct in_addr
1461 addr2mask(struct in_addr addr)
1462 {
1463   u_int32_t haddr = ntohl(addr.s_addr);
1464 
1465   haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET :
1466           IN_CLASSB(haddr) ? IN_CLASSB_NET :
1467           IN_CLASSC_NET;
1468   addr.s_addr = htonl(haddr);
1469 
1470   return addr;
1471 }
1472