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