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