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