datalink.c revision 102413
1/*-
2 * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/usr.sbin/ppp/datalink.c 102413 2002-08-25 13:30:43Z charnier $
27 */
28
29#include <sys/param.h>
30#include <netinet/in.h>
31#include <netinet/in_systm.h>
32#include <netinet/ip.h>
33#include <sys/socket.h>
34#include <sys/un.h>
35
36#include <ctype.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <sys/uio.h>
41#include <termios.h>
42
43#include "layer.h"
44#include "mbuf.h"
45#include "log.h"
46#include "defs.h"
47#include "timer.h"
48#include "fsm.h"
49#include "descriptor.h"
50#include "lqr.h"
51#include "hdlc.h"
52#include "lcp.h"
53#include "async.h"
54#include "throughput.h"
55#include "ccp.h"
56#include "link.h"
57#include "physical.h"
58#include "iplist.h"
59#include "slcompress.h"
60#include "ncpaddr.h"
61#include "ipcp.h"
62#include "filter.h"
63#include "mp.h"
64#ifndef NORADIUS
65#include "radius.h"
66#endif
67#include "ipv6cp.h"
68#include "ncp.h"
69#include "bundle.h"
70#include "chat.h"
71#include "auth.h"
72#include "prompt.h"
73#include "proto.h"
74#include "pap.h"
75#include "chap.h"
76#include "command.h"
77#include "cbcp.h"
78#include "datalink.h"
79
80static void datalink_LoginDone(struct datalink *);
81static void datalink_NewState(struct datalink *, int);
82
83static void
84datalink_OpenTimeout(void *v)
85{
86  struct datalink *dl = (struct datalink *)v;
87
88  timer_Stop(&dl->dial.timer);
89  if (dl->state == DATALINK_OPENING)
90    log_Printf(LogCHAT, "%s: Redial timer expired.\n", dl->name);
91}
92
93static int
94datalink_StartDialTimer(struct datalink *dl, int Timeout)
95{
96  int result = Timeout;
97
98  timer_Stop(&dl->dial.timer);
99  if (Timeout < 0)
100    result = (random() % DIAL_TIMEOUT) + 1;
101  dl->dial.timer.load = result ? result * SECTICKS : 1;
102  dl->dial.timer.func = datalink_OpenTimeout;
103  dl->dial.timer.name = "dial";
104  dl->dial.timer.arg = dl;
105  timer_Start(&dl->dial.timer);
106  if (dl->state == DATALINK_OPENING)
107    log_Printf(LogPHASE, "%s: Enter pause (%d) for redialing.\n",
108               dl->name, result);
109  return result;
110}
111
112static void
113datalink_HangupDone(struct datalink *dl)
114{
115  if (dl->physical->type == PHYS_DEDICATED && !dl->bundle->CleaningUp &&
116      dl->physical->fd != -1) {
117    /* Don't close our device if the link is dedicated */
118    datalink_LoginDone(dl);
119    return;
120  }
121
122  chat_Finish(&dl->chat);
123  physical_Close(dl->physical);
124  dl->phone.chosen = "N/A";
125
126  if (dl->cbcp.required) {
127    log_Printf(LogPHASE, "Call peer back on %s\n", dl->cbcp.fsm.phone);
128    dl->cfg.callback.opmask = 0;
129    strncpy(dl->cfg.phone.list, dl->cbcp.fsm.phone,
130            sizeof dl->cfg.phone.list - 1);
131    dl->cfg.phone.list[sizeof dl->cfg.phone.list - 1] = '\0';
132    dl->phone.alt = dl->phone.next = NULL;
133    dl->reconnect_tries = dl->cfg.reconnect.max;
134    dl->dial.tries = dl->cfg.dial.max;
135    dl->dial.incs = 0;
136    dl->script.run = 1;
137    dl->script.packetmode = 1;
138    if (!physical_SetMode(dl->physical, PHYS_BACKGROUND))
139      log_Printf(LogERROR, "Oops - can't change mode to BACKGROUND (gulp) !\n");
140    bundle_LinksRemoved(dl->bundle);
141    /* if dial.timeout is < 0 (random), we don't override fsm.delay */
142    if (dl->cbcp.fsm.delay < dl->cfg.dial.timeout)
143      dl->cbcp.fsm.delay = dl->cfg.dial.timeout;
144    datalink_StartDialTimer(dl, dl->cbcp.fsm.delay);
145    cbcp_Down(&dl->cbcp);
146    datalink_NewState(dl, DATALINK_OPENING);
147    if (bundle_Phase(dl->bundle) == PHASE_DEAD ||
148        bundle_Phase(dl->bundle) == PHASE_TERMINATE)
149      bundle_NewPhase(dl->bundle, PHASE_ESTABLISH);
150  } else if (dl->bundle->CleaningUp ||
151      (dl->physical->type == PHYS_DIRECT) ||
152      ((!dl->dial.tries || (dl->dial.tries < 0 && !dl->reconnect_tries)) &&
153       !(dl->physical->type & (PHYS_DDIAL|PHYS_DEDICATED)))) {
154    datalink_NewState(dl, DATALINK_CLOSED);
155    dl->dial.tries = -1;
156    dl->dial.incs = 0;
157    dl->reconnect_tries = 0;
158    bundle_LinkClosed(dl->bundle, dl);
159    if (!dl->bundle->CleaningUp &&
160        !(dl->physical->type & (PHYS_DIRECT|PHYS_BACKGROUND|PHYS_FOREGROUND)))
161      datalink_StartDialTimer(dl, datalink_GetDialTimeout(dl));
162  } else {
163    datalink_NewState(dl, DATALINK_OPENING);
164    if (bundle_Phase(dl->bundle) == PHASE_DEAD ||
165        bundle_Phase(dl->bundle) == PHASE_TERMINATE)
166      bundle_NewPhase(dl->bundle, PHASE_ESTABLISH);
167    if (dl->dial.tries < 0) {
168      datalink_StartDialTimer(dl, dl->cfg.reconnect.timeout);
169      dl->dial.tries = dl->cfg.dial.max;
170      dl->dial.incs = 0;
171      dl->reconnect_tries--;
172      log_Printf(LogCHAT, "%s: Reconnect try %d of %d\n",
173                 dl->name, dl->cfg.reconnect.max - dl->reconnect_tries,
174                 dl->cfg.reconnect.max);
175      bundle_Notify(dl->bundle, EX_RECONNECT);
176    } else {
177      if (dl->phone.next == NULL)
178        datalink_StartDialTimer(dl, datalink_GetDialTimeout(dl));
179      else
180        datalink_StartDialTimer(dl, dl->cfg.dial.next_timeout);
181      bundle_Notify(dl->bundle, EX_REDIAL);
182    }
183  }
184}
185
186const char *
187datalink_ChoosePhoneNumber(struct datalink *dl)
188{
189  char *phone;
190
191  if (dl->phone.alt == NULL) {
192    if (dl->phone.next == NULL) {
193      strncpy(dl->phone.list, dl->cfg.phone.list, sizeof dl->phone.list - 1);
194      dl->phone.list[sizeof dl->phone.list - 1] = '\0';
195      if (*dl->phone.list == '\0')
196        return "";
197      dl->phone.next = dl->phone.list;
198    }
199    dl->phone.alt = strsep(&dl->phone.next, ":");
200  }
201  phone = strsep(&dl->phone.alt, "|");
202  dl->phone.chosen = *phone ? phone : "[NONE]";
203  if (*phone)
204    log_Printf(LogCHAT, "Phone: %s\n", phone);
205  return phone;
206}
207
208static void
209datalink_LoginDone(struct datalink *dl)
210{
211  chat_Finish(&dl->chat);
212
213  if (!dl->script.packetmode) {
214    dl->dial.tries = -1;
215    dl->dial.incs = 0;
216    datalink_NewState(dl, DATALINK_READY);
217  } else if (!physical_Raw(dl->physical)) {
218    dl->dial.tries = 0;
219    log_Printf(LogWARN, "datalink_LoginDone: Not connected.\n");
220    if (dl->script.run) {
221      datalink_NewState(dl, DATALINK_LOGOUT);
222      if (!chat_Setup(&dl->chat, dl->cfg.script.logout, NULL))
223        log_Printf(LogWARN, "Invalid logout script\n");
224    } else {
225      physical_StopDeviceTimer(dl->physical);
226      if (dl->physical->type == PHYS_DEDICATED)
227        /* force a redial timeout */
228        physical_Close(dl->physical);
229      datalink_HangupDone(dl);
230    }
231  } else {
232    dl->dial.tries = -1;
233    dl->dial.incs = 0;
234
235    hdlc_Init(&dl->physical->hdlc, &dl->physical->link.lcp);
236    async_Setup(&dl->physical->async);
237
238    lcp_Setup(&dl->physical->link.lcp, dl->state == DATALINK_READY ?
239              0 : dl->physical->link.lcp.cfg.openmode);
240    ccp_Setup(&dl->physical->link.ccp);
241
242    datalink_NewState(dl, DATALINK_LCP);
243    fsm_Up(&dl->physical->link.lcp.fsm);
244    fsm_Open(&dl->physical->link.lcp.fsm);
245  }
246}
247
248static int
249datalink_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e,
250                   int *n)
251{
252  struct datalink *dl = descriptor2datalink(d);
253  int result;
254
255  result = 0;
256  switch (dl->state) {
257    case DATALINK_CLOSED:
258      if ((dl->physical->type & (PHYS_DIRECT|PHYS_DEDICATED|PHYS_BACKGROUND|
259                                 PHYS_FOREGROUND|PHYS_DDIAL)) &&
260          !dl->bundle->CleaningUp)
261        /*
262         * Our first time in - DEDICATED & DDIAL never come down, and
263         * DIRECT, FOREGROUND & BACKGROUND get deleted when they enter
264         * DATALINK_CLOSED.  Go to DATALINK_OPENING via datalink_Up()
265         * and fall through.
266         */
267        datalink_Up(dl, 1, 1);
268      else
269        break;
270      /* FALLTHROUGH */
271
272    case DATALINK_OPENING:
273      if (dl->dial.timer.state != TIMER_RUNNING) {
274        if (--dl->dial.tries < 0)
275          dl->dial.tries = 0;
276        if (physical_Open(dl->physical, dl->bundle) >= 0) {
277          log_WritePrompts(dl, "%s: Entering terminal mode on %s\r\n"
278                           "Type `~?' for help\r\n", dl->name,
279                           dl->physical->name.full);
280          if (dl->script.run) {
281            datalink_NewState(dl, DATALINK_DIAL);
282            if (!chat_Setup(&dl->chat, dl->cfg.script.dial,
283                            *dl->cfg.script.dial ?
284                            datalink_ChoosePhoneNumber(dl) : ""))
285              log_Printf(LogWARN, "Invalid dial script\n");
286            if (!(dl->physical->type & (PHYS_DDIAL|PHYS_DEDICATED)) &&
287                dl->cfg.dial.max)
288              log_Printf(LogCHAT, "%s: Dial attempt %u of %d\n",
289                        dl->name, dl->cfg.dial.max - dl->dial.tries,
290                        dl->cfg.dial.max);
291          } else
292            datalink_NewState(dl, DATALINK_CARRIER);
293          return datalink_UpdateSet(d, r, w, e, n);
294        } else {
295          if (!(dl->physical->type & (PHYS_DDIAL|PHYS_DEDICATED)) &&
296              dl->cfg.dial.max)
297            log_Printf(LogCHAT, "Failed to open device (attempt %u of %d)\n",
298                       dl->cfg.dial.max - dl->dial.tries, dl->cfg.dial.max);
299          else
300            log_Printf(LogCHAT, "Failed to open device\n");
301
302          if (dl->bundle->CleaningUp ||
303              (!(dl->physical->type & (PHYS_DDIAL|PHYS_DEDICATED)) &&
304               dl->cfg.dial.max && dl->dial.tries == 0)) {
305            datalink_NewState(dl, DATALINK_CLOSED);
306            dl->reconnect_tries = 0;
307            dl->dial.tries = -1;
308            log_WritePrompts(dl, "Failed to open %s\n",
309                             dl->physical->name.full);
310            bundle_LinkClosed(dl->bundle, dl);
311          }
312          if (!dl->bundle->CleaningUp) {
313            int timeout;
314
315            timeout = datalink_StartDialTimer(dl, datalink_GetDialTimeout(dl));
316            bundle_Notify(dl->bundle, EX_REDIAL);
317            log_WritePrompts(dl, "Failed to open %s, pause %d seconds\n",
318                             dl->physical->name.full, timeout);
319          }
320        }
321      }
322      break;
323
324    case DATALINK_CARRIER:
325      /* Wait for carrier on the device */
326      switch (physical_AwaitCarrier(dl->physical)) {
327        case CARRIER_PENDING:
328          log_Printf(LogDEBUG, "Waiting for carrier\n");
329          return 0;	/* A device timer is running to wake us up again */
330
331        case CARRIER_OK:
332          if (dl->script.run) {
333            datalink_NewState(dl, DATALINK_LOGIN);
334            if (!chat_Setup(&dl->chat, dl->cfg.script.login, NULL))
335              log_Printf(LogWARN, "Invalid login script\n");
336          } else
337            datalink_LoginDone(dl);
338          return datalink_UpdateSet(d, r, w, e, n);
339
340        case CARRIER_LOST:
341          physical_Offline(dl->physical);	/* Is this required ? */
342          if (dl->script.run) {
343            datalink_NewState(dl, DATALINK_HANGUP);
344            if (!chat_Setup(&dl->chat, dl->cfg.script.hangup, NULL))
345              log_Printf(LogWARN, "Invalid hangup script\n");
346            return datalink_UpdateSet(d, r, w, e, n);
347          } else {
348            datalink_HangupDone(dl);
349            return 0;	/* Maybe bundle_CleanDatalinks() has something to do */
350          }
351      }
352
353    case DATALINK_HANGUP:
354    case DATALINK_DIAL:
355    case DATALINK_LOGOUT:
356    case DATALINK_LOGIN:
357      result = descriptor_UpdateSet(&dl->chat.desc, r, w, e, n);
358      switch (dl->chat.state) {
359        case CHAT_DONE:
360          /* script succeeded */
361          switch(dl->state) {
362            case DATALINK_HANGUP:
363              datalink_HangupDone(dl);
364              break;
365            case DATALINK_DIAL:
366              datalink_NewState(dl, DATALINK_CARRIER);
367              return datalink_UpdateSet(d, r, w, e, n);
368            case DATALINK_LOGOUT:
369              datalink_NewState(dl, DATALINK_HANGUP);
370              physical_Offline(dl->physical);
371              if (!chat_Setup(&dl->chat, dl->cfg.script.hangup, NULL))
372                log_Printf(LogWARN, "Invalid hangup script\n");
373              return datalink_UpdateSet(d, r, w, e, n);
374            case DATALINK_LOGIN:
375              dl->phone.alt = NULL;
376              datalink_LoginDone(dl);
377              return datalink_UpdateSet(d, r, w, e, n);
378          }
379          break;
380        case CHAT_FAILED:
381          /* Going down - script failed */
382          log_Printf(LogWARN, "Chat script failed\n");
383          switch(dl->state) {
384            case DATALINK_HANGUP:
385              datalink_HangupDone(dl);
386              break;
387            case DATALINK_DIAL:
388            case DATALINK_LOGOUT:
389            case DATALINK_LOGIN:
390              datalink_NewState(dl, DATALINK_HANGUP);
391              physical_Offline(dl->physical);
392              if (!chat_Setup(&dl->chat, dl->cfg.script.hangup, NULL))
393                log_Printf(LogWARN, "Invalid hangup script\n");
394              return datalink_UpdateSet(d, r, w, e, n);
395          }
396          break;
397      }
398      break;
399
400    case DATALINK_READY:
401    case DATALINK_LCP:
402    case DATALINK_AUTH:
403    case DATALINK_CBCP:
404    case DATALINK_OPEN:
405      result = descriptor_UpdateSet(&dl->chap.desc, r, w, e, n) +
406               descriptor_UpdateSet(&dl->physical->desc, r, w, e, n);
407      break;
408  }
409  return result;
410}
411
412int
413datalink_RemoveFromSet(struct datalink *dl, fd_set *r, fd_set *w, fd_set *e)
414{
415  return physical_RemoveFromSet(dl->physical, r, w, e);
416}
417
418static int
419datalink_IsSet(struct fdescriptor *d, const fd_set *fdset)
420{
421  struct datalink *dl = descriptor2datalink(d);
422
423  switch (dl->state) {
424    case DATALINK_CLOSED:
425    case DATALINK_OPENING:
426      break;
427
428    case DATALINK_HANGUP:
429    case DATALINK_DIAL:
430    case DATALINK_LOGOUT:
431    case DATALINK_LOGIN:
432      return descriptor_IsSet(&dl->chat.desc, fdset);
433
434    case DATALINK_READY:
435    case DATALINK_LCP:
436    case DATALINK_AUTH:
437    case DATALINK_CBCP:
438    case DATALINK_OPEN:
439      return descriptor_IsSet(&dl->chap.desc, fdset) ? 1 :
440             descriptor_IsSet(&dl->physical->desc, fdset);
441  }
442  return 0;
443}
444
445static void
446datalink_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
447{
448  struct datalink *dl = descriptor2datalink(d);
449
450  switch (dl->state) {
451    case DATALINK_CLOSED:
452    case DATALINK_OPENING:
453      break;
454
455    case DATALINK_HANGUP:
456    case DATALINK_DIAL:
457    case DATALINK_LOGOUT:
458    case DATALINK_LOGIN:
459      descriptor_Read(&dl->chat.desc, bundle, fdset);
460      break;
461
462    case DATALINK_READY:
463    case DATALINK_LCP:
464    case DATALINK_AUTH:
465    case DATALINK_CBCP:
466    case DATALINK_OPEN:
467      if (descriptor_IsSet(&dl->chap.desc, fdset))
468        descriptor_Read(&dl->chap.desc, bundle, fdset);
469      if (descriptor_IsSet(&dl->physical->desc, fdset))
470        descriptor_Read(&dl->physical->desc, bundle, fdset);
471      break;
472  }
473}
474
475static int
476datalink_Write(struct fdescriptor *d, struct bundle *bundle,
477               const fd_set *fdset)
478{
479  struct datalink *dl = descriptor2datalink(d);
480  int result = 0;
481
482  switch (dl->state) {
483    case DATALINK_CLOSED:
484    case DATALINK_OPENING:
485      break;
486
487    case DATALINK_HANGUP:
488    case DATALINK_DIAL:
489    case DATALINK_LOGOUT:
490    case DATALINK_LOGIN:
491      if ((result = descriptor_Write(&dl->chat.desc, bundle, fdset)) == -1) {
492        datalink_ComeDown(dl, CLOSE_NORMAL);
493        result = 0;
494      }
495      break;
496
497    case DATALINK_READY:
498    case DATALINK_LCP:
499    case DATALINK_AUTH:
500    case DATALINK_CBCP:
501    case DATALINK_OPEN:
502      if (descriptor_IsSet(&dl->chap.desc, fdset))
503        switch (descriptor_Write(&dl->chap.desc, bundle, fdset)) {
504        case -1:
505          datalink_ComeDown(dl, CLOSE_NORMAL);
506          break;
507        case 1:
508          result++;
509        }
510      if (descriptor_IsSet(&dl->physical->desc, fdset))
511        switch (descriptor_Write(&dl->physical->desc, bundle, fdset)) {
512        case -1:
513          datalink_ComeDown(dl, CLOSE_NORMAL);
514          break;
515        case 1:
516          result++;
517        }
518      break;
519  }
520
521  return result;
522}
523
524void
525datalink_ComeDown(struct datalink *dl, int how)
526{
527  int stayonline;
528
529  if (how == CLOSE_LCP)
530    datalink_DontHangup(dl);
531  else if (how == CLOSE_STAYDOWN)
532    datalink_StayDown(dl);
533
534  stayonline = dl->stayonline;
535  dl->stayonline = 0;
536
537  if (dl->state >= DATALINK_READY && stayonline) {
538    physical_StopDeviceTimer(dl->physical);
539    datalink_NewState(dl, DATALINK_READY);
540  } else if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) {
541    physical_Offline(dl->physical);
542    if (dl->script.run && dl->state != DATALINK_OPENING) {
543      if (dl->state == DATALINK_LOGOUT) {
544        datalink_NewState(dl, DATALINK_HANGUP);
545        if (!chat_Setup(&dl->chat, dl->cfg.script.hangup, NULL))
546          log_Printf(LogWARN, "Invalid hangup script\n");
547      } else {
548        datalink_NewState(dl, DATALINK_LOGOUT);
549        if (!chat_Setup(&dl->chat, dl->cfg.script.logout, NULL))
550          log_Printf(LogWARN, "Invalid logout script\n");
551      }
552    } else
553      datalink_HangupDone(dl);
554  }
555}
556
557static void
558datalink_LayerStart(void *v, struct fsm *fp)
559{
560  /* The given FSM is about to start up ! */
561  struct datalink *dl = (struct datalink *)v;
562
563  if (fp->proto == PROTO_LCP)
564    (*dl->parent->LayerStart)(dl->parent->object, fp);
565}
566
567static void
568datalink_LayerUp(void *v, struct fsm *fp)
569{
570  /* The given fsm is now up */
571  struct datalink *dl = (struct datalink *)v;
572  struct lcp *lcp = &dl->physical->link.lcp;
573
574  if (fp->proto == PROTO_LCP) {
575    datalink_GotAuthname(dl, "");
576    lcp->auth_ineed = lcp->want_auth;
577    lcp->auth_iwait = lcp->his_auth;
578    if (lcp->his_auth || lcp->want_auth) {
579      if (bundle_Phase(dl->bundle) != PHASE_NETWORK)
580        bundle_NewPhase(dl->bundle, PHASE_AUTHENTICATE);
581      log_Printf(LogPHASE, "%s: his = %s, mine = %s\n", dl->name,
582                Auth2Nam(lcp->his_auth, lcp->his_authtype),
583                Auth2Nam(lcp->want_auth, lcp->want_authtype));
584      if (lcp->his_auth == PROTO_PAP)
585        auth_StartReq(&dl->pap);
586      if (lcp->want_auth == PROTO_CHAP)
587        auth_StartReq(&dl->chap.auth);
588    } else
589      datalink_AuthOk(dl);
590  } else if (fp->proto == PROTO_CCP)
591    (*dl->parent->LayerUp)(dl->parent->object, &dl->physical->link.ccp.fsm);
592}
593
594static void
595datalink_AuthReInit(struct datalink *dl)
596{
597  auth_StopTimer(&dl->pap);
598  auth_StopTimer(&dl->chap.auth);
599  chap_ReInit(&dl->chap);
600}
601
602void
603datalink_GotAuthname(struct datalink *dl, const char *name)
604{
605  strncpy(dl->peer.authname, name, sizeof dl->peer.authname - 1);
606  dl->peer.authname[sizeof dl->peer.authname - 1] = '\0';
607}
608
609void
610datalink_NCPUp(struct datalink *dl)
611{
612  int ccpok = ccp_SetOpenMode(&dl->physical->link.ccp);
613
614  if (dl->physical->link.lcp.want_mrru && dl->physical->link.lcp.his_mrru) {
615    /* we've authenticated in multilink mode ! */
616    switch (mp_Up(&dl->bundle->ncp.mp, dl)) {
617      case MP_LINKSENT:
618        /* We've handed the link off to another ppp (well, we will soon) ! */
619        return;
620      case MP_UP:
621        /* First link in the bundle */
622        auth_Select(dl->bundle, dl->peer.authname);
623        bundle_CalculateBandwidth(dl->bundle);
624        /* FALLTHROUGH */
625      case MP_ADDED:
626        /* We're in multilink mode ! */
627        dl->physical->link.ccp.fsm.open_mode = OPEN_PASSIVE;	/* override */
628        bundle_CalculateBandwidth(dl->bundle);
629        break;
630      case MP_FAILED:
631        datalink_AuthNotOk(dl);
632        return;
633    }
634  } else if (bundle_Phase(dl->bundle) == PHASE_NETWORK) {
635    log_Printf(LogPHASE, "%s: Already in NETWORK phase\n", dl->name);
636    datalink_NewState(dl, DATALINK_OPEN);
637    bundle_CalculateBandwidth(dl->bundle);
638    (*dl->parent->LayerUp)(dl->parent->object, &dl->physical->link.lcp.fsm);
639    return;
640  } else {
641    dl->bundle->ncp.mp.peer = dl->peer;
642    ncp_SetLink(&dl->bundle->ncp, &dl->physical->link);
643    auth_Select(dl->bundle, dl->peer.authname);
644  }
645
646  if (ccpok) {
647    fsm_Up(&dl->physical->link.ccp.fsm);
648    fsm_Open(&dl->physical->link.ccp.fsm);
649  }
650  datalink_NewState(dl, DATALINK_OPEN);
651  bundle_NewPhase(dl->bundle, PHASE_NETWORK);
652  (*dl->parent->LayerUp)(dl->parent->object, &dl->physical->link.lcp.fsm);
653}
654
655void
656datalink_CBCPComplete(struct datalink *dl)
657{
658  datalink_NewState(dl, DATALINK_LCP);
659  datalink_AuthReInit(dl);
660  fsm_Close(&dl->physical->link.lcp.fsm);
661}
662
663void
664datalink_CBCPFailed(struct datalink *dl)
665{
666  cbcp_Down(&dl->cbcp);
667  datalink_CBCPComplete(dl);
668}
669
670void
671datalink_AuthOk(struct datalink *dl)
672{
673  if ((dl->physical->link.lcp.his_callback.opmask &
674       CALLBACK_BIT(CALLBACK_CBCP) ||
675       dl->physical->link.lcp.want_callback.opmask &
676       CALLBACK_BIT(CALLBACK_CBCP)) &&
677      !(dl->physical->link.lcp.want_callback.opmask &
678        CALLBACK_BIT(CALLBACK_AUTH))) {
679    /* We must have agreed CBCP if AUTH isn't there any more */
680    datalink_NewState(dl, DATALINK_CBCP);
681    cbcp_Up(&dl->cbcp);
682  } else if (dl->physical->link.lcp.want_callback.opmask) {
683    /* It's not CBCP */
684    log_Printf(LogPHASE, "%s: Shutdown and await peer callback\n", dl->name);
685    datalink_NewState(dl, DATALINK_LCP);
686    datalink_AuthReInit(dl);
687    fsm_Close(&dl->physical->link.lcp.fsm);
688  } else
689    switch (dl->physical->link.lcp.his_callback.opmask) {
690      case 0:
691        datalink_NCPUp(dl);
692        break;
693
694      case CALLBACK_BIT(CALLBACK_AUTH):
695        auth_SetPhoneList(dl->peer.authname, dl->cbcp.fsm.phone,
696                          sizeof dl->cbcp.fsm.phone);
697        if (*dl->cbcp.fsm.phone == '\0' || !strcmp(dl->cbcp.fsm.phone, "*")) {
698          log_Printf(LogPHASE, "%s: %s cannot be called back\n", dl->name,
699                     dl->peer.authname);
700          *dl->cbcp.fsm.phone = '\0';
701        } else {
702          char *ptr = strchr(dl->cbcp.fsm.phone, ',');
703          if (ptr)
704            *ptr = '\0';	/* Call back on the first number */
705          log_Printf(LogPHASE, "%s: Calling peer back on %s\n", dl->name,
706                     dl->cbcp.fsm.phone);
707          dl->cbcp.required = 1;
708        }
709        dl->cbcp.fsm.delay = 0;
710        datalink_NewState(dl, DATALINK_LCP);
711        datalink_AuthReInit(dl);
712        fsm_Close(&dl->physical->link.lcp.fsm);
713        break;
714
715      case CALLBACK_BIT(CALLBACK_E164):
716        strncpy(dl->cbcp.fsm.phone, dl->physical->link.lcp.his_callback.msg,
717                sizeof dl->cbcp.fsm.phone - 1);
718        dl->cbcp.fsm.phone[sizeof dl->cbcp.fsm.phone - 1] = '\0';
719        log_Printf(LogPHASE, "%s: Calling peer back on %s\n", dl->name,
720                   dl->cbcp.fsm.phone);
721        dl->cbcp.required = 1;
722        dl->cbcp.fsm.delay = 0;
723        datalink_NewState(dl, DATALINK_LCP);
724        datalink_AuthReInit(dl);
725        fsm_Close(&dl->physical->link.lcp.fsm);
726        break;
727
728      default:
729        log_Printf(LogPHASE, "%s: Oops - Should have NAK'd peer callback !\n",
730                   dl->name);
731        datalink_NewState(dl, DATALINK_LCP);
732        datalink_AuthReInit(dl);
733        fsm_Close(&dl->physical->link.lcp.fsm);
734        break;
735    }
736}
737
738void
739datalink_AuthNotOk(struct datalink *dl)
740{
741  datalink_NewState(dl, DATALINK_LCP);
742  datalink_AuthReInit(dl);
743  fsm_Close(&dl->physical->link.lcp.fsm);
744}
745
746static void
747datalink_LayerDown(void *v, struct fsm *fp)
748{
749  /* The given FSM has been told to come down */
750  struct datalink *dl = (struct datalink *)v;
751
752  if (fp->proto == PROTO_LCP) {
753    switch (dl->state) {
754      case DATALINK_OPEN:
755        peerid_Init(&dl->peer);
756        fsm2initial(&dl->physical->link.ccp.fsm);
757        datalink_NewState(dl, DATALINK_LCP);  /* before parent TLD */
758        (*dl->parent->LayerDown)(dl->parent->object, fp);
759        /* FALLTHROUGH (just in case) */
760
761      case DATALINK_CBCP:
762        if (!dl->cbcp.required)
763          cbcp_Down(&dl->cbcp);
764        /* FALLTHROUGH (just in case) */
765
766      case DATALINK_AUTH:
767        timer_Stop(&dl->pap.authtimer);
768        timer_Stop(&dl->chap.auth.authtimer);
769    }
770    datalink_NewState(dl, DATALINK_LCP);
771    datalink_AuthReInit(dl);
772  }
773}
774
775static void
776datalink_LayerFinish(void *v, struct fsm *fp)
777{
778  /* The given fsm is now down */
779  struct datalink *dl = (struct datalink *)v;
780
781  if (fp->proto == PROTO_LCP) {
782    fsm2initial(fp);
783    (*dl->parent->LayerFinish)(dl->parent->object, fp);
784    datalink_ComeDown(dl, CLOSE_NORMAL);
785  } else if (fp->state == ST_CLOSED && fp->open_mode == OPEN_PASSIVE)
786    fsm_Open(fp);		/* CCP goes to ST_STOPPED */
787}
788
789struct datalink *
790datalink_Create(const char *name, struct bundle *bundle, int type)
791{
792  struct datalink *dl;
793
794  dl = (struct datalink *)malloc(sizeof(struct datalink));
795  if (dl == NULL)
796    return dl;
797
798  dl->desc.type = DATALINK_DESCRIPTOR;
799  dl->desc.UpdateSet = datalink_UpdateSet;
800  dl->desc.IsSet = datalink_IsSet;
801  dl->desc.Read = datalink_Read;
802  dl->desc.Write = datalink_Write;
803
804  dl->state = DATALINK_CLOSED;
805
806  *dl->cfg.script.dial = '\0';
807  *dl->cfg.script.login = '\0';
808  *dl->cfg.script.logout = '\0';
809  *dl->cfg.script.hangup = '\0';
810  *dl->cfg.phone.list = '\0';
811  *dl->phone.list = '\0';
812  dl->phone.next = NULL;
813  dl->phone.alt = NULL;
814  dl->phone.chosen = "N/A";
815  dl->stayonline = 0;
816  dl->script.run = 1;
817  dl->script.packetmode = 1;
818  mp_linkInit(&dl->mp);
819
820  dl->bundle = bundle;
821  dl->next = NULL;
822
823  memset(&dl->dial.timer, '\0', sizeof dl->dial.timer);
824
825  dl->dial.tries = 0;
826  dl->cfg.dial.max = 1;
827  dl->cfg.dial.next_timeout = DIAL_NEXT_TIMEOUT;
828  dl->cfg.dial.timeout = DIAL_TIMEOUT;
829  dl->cfg.dial.inc = 0;
830  dl->cfg.dial.maxinc = 10;
831
832  dl->reconnect_tries = 0;
833  dl->cfg.reconnect.max = 0;
834  dl->cfg.reconnect.timeout = RECONNECT_TIMEOUT;
835
836  dl->cfg.callback.opmask = 0;
837  dl->cfg.cbcp.delay = 0;
838  *dl->cfg.cbcp.phone = '\0';
839  dl->cfg.cbcp.fsmretry = DEF_FSMRETRY;
840
841  dl->name = strdup(name);
842  peerid_Init(&dl->peer);
843  dl->parent = &bundle->fsm;
844  dl->fsmp.LayerStart = datalink_LayerStart;
845  dl->fsmp.LayerUp = datalink_LayerUp;
846  dl->fsmp.LayerDown = datalink_LayerDown;
847  dl->fsmp.LayerFinish = datalink_LayerFinish;
848  dl->fsmp.object = dl;
849
850  if ((dl->physical = physical_Create(dl, type)) == NULL) {
851    free(dl->name);
852    free(dl);
853    return NULL;
854  }
855
856  pap_Init(&dl->pap, dl->physical);
857  chap_Init(&dl->chap, dl->physical);
858  cbcp_Init(&dl->cbcp, dl->physical);
859
860  memset(&dl->chat, '\0', sizeof dl->chat);	/* Force buf{start,end} reset */
861  chat_Init(&dl->chat, dl->physical);
862
863  log_Printf(LogPHASE, "%s: Created in %s state\n",
864             dl->name, datalink_State(dl));
865
866  return dl;
867}
868
869struct datalink *
870datalink_Clone(struct datalink *odl, const char *name)
871{
872  struct datalink *dl;
873
874  dl = (struct datalink *)malloc(sizeof(struct datalink));
875  if (dl == NULL)
876    return dl;
877
878  dl->desc.type = DATALINK_DESCRIPTOR;
879  dl->desc.UpdateSet = datalink_UpdateSet;
880  dl->desc.IsSet = datalink_IsSet;
881  dl->desc.Read = datalink_Read;
882  dl->desc.Write = datalink_Write;
883
884  dl->state = DATALINK_CLOSED;
885
886  memcpy(&dl->cfg, &odl->cfg, sizeof dl->cfg);
887  mp_linkInit(&dl->mp);
888  *dl->phone.list = '\0';
889  dl->phone.next = NULL;
890  dl->phone.alt = NULL;
891  dl->phone.chosen = "N/A";
892  dl->bundle = odl->bundle;
893  dl->next = NULL;
894  memset(&dl->dial.timer, '\0', sizeof dl->dial.timer);
895  dl->dial.tries = 0;
896  dl->reconnect_tries = 0;
897  dl->name = strdup(name);
898  peerid_Init(&dl->peer);
899  dl->parent = odl->parent;
900  memcpy(&dl->fsmp, &odl->fsmp, sizeof dl->fsmp);
901  dl->fsmp.object = dl;
902
903  if ((dl->physical = physical_Create(dl, PHYS_INTERACTIVE)) == NULL) {
904    free(dl->name);
905    free(dl);
906    return NULL;
907  }
908  pap_Init(&dl->pap, dl->physical);
909  dl->pap.cfg = odl->pap.cfg;
910
911  chap_Init(&dl->chap, dl->physical);
912  dl->chap.auth.cfg = odl->chap.auth.cfg;
913
914  memcpy(&dl->physical->cfg, &odl->physical->cfg, sizeof dl->physical->cfg);
915  memcpy(&dl->physical->link.lcp.cfg, &odl->physical->link.lcp.cfg,
916         sizeof dl->physical->link.lcp.cfg);
917  memcpy(&dl->physical->link.ccp.cfg, &odl->physical->link.ccp.cfg,
918         sizeof dl->physical->link.ccp.cfg);
919  memcpy(&dl->physical->async.cfg, &odl->physical->async.cfg,
920         sizeof dl->physical->async.cfg);
921
922  cbcp_Init(&dl->cbcp, dl->physical);
923
924  memset(&dl->chat, '\0', sizeof dl->chat);	/* Force buf{start,end} reset */
925  chat_Init(&dl->chat, dl->physical);
926
927  log_Printf(LogPHASE, "%s: Cloned in %s state\n",
928             dl->name, datalink_State(dl));
929
930  return dl;
931}
932
933struct datalink *
934datalink_Destroy(struct datalink *dl)
935{
936  struct datalink *result;
937
938  if (dl->state != DATALINK_CLOSED) {
939    log_Printf(LogERROR, "Oops, destroying a datalink in state %s\n",
940              datalink_State(dl));
941    switch (dl->state) {
942      case DATALINK_HANGUP:
943      case DATALINK_DIAL:
944      case DATALINK_LOGIN:
945        chat_Finish(&dl->chat);		/* Gotta blat the timers ! */
946        break;
947    }
948  }
949
950  chat_Destroy(&dl->chat);
951  timer_Stop(&dl->dial.timer);
952  result = dl->next;
953  physical_Destroy(dl->physical);
954  free(dl->name);
955  free(dl);
956
957  return result;
958}
959
960void
961datalink_Up(struct datalink *dl, int runscripts, int packetmode)
962{
963  if (dl->physical->type & (PHYS_DIRECT|PHYS_DEDICATED))
964    /* Ignore scripts */
965    runscripts = 0;
966
967  switch (dl->state) {
968    case DATALINK_CLOSED:
969      if (bundle_Phase(dl->bundle) == PHASE_DEAD ||
970          bundle_Phase(dl->bundle) == PHASE_TERMINATE)
971        bundle_NewPhase(dl->bundle, PHASE_ESTABLISH);
972      datalink_NewState(dl, DATALINK_OPENING);
973      dl->reconnect_tries =
974        dl->physical->type == PHYS_DIRECT ? 0 : dl->cfg.reconnect.max;
975      dl->dial.tries = dl->cfg.dial.max;
976      dl->script.run = runscripts;
977      dl->script.packetmode = packetmode;
978      break;
979
980    case DATALINK_OPENING:
981      if (!dl->script.run && runscripts)
982        dl->script.run = 1;
983      /* FALLTHROUGH */
984
985    case DATALINK_DIAL:
986    case DATALINK_LOGIN:
987    case DATALINK_READY:
988      if (!dl->script.packetmode && packetmode) {
989        dl->script.packetmode = 1;
990        if (dl->state == DATALINK_READY) {
991          dl->script.run = 0;
992          datalink_NewState(dl, DATALINK_CARRIER);
993        }
994      }
995      break;
996  }
997}
998
999void
1000datalink_Close(struct datalink *dl, int how)
1001{
1002  /* Please close */
1003  switch (dl->state) {
1004    case DATALINK_OPEN:
1005      peerid_Init(&dl->peer);
1006      fsm2initial(&dl->physical->link.ccp.fsm);
1007      /* FALLTHROUGH */
1008
1009    case DATALINK_CBCP:
1010    case DATALINK_AUTH:
1011    case DATALINK_LCP:
1012      datalink_AuthReInit(dl);
1013      if (how == CLOSE_LCP)
1014        datalink_DontHangup(dl);
1015      else if (how == CLOSE_STAYDOWN)
1016        datalink_StayDown(dl);
1017      fsm_Close(&dl->physical->link.lcp.fsm);
1018      break;
1019
1020    default:
1021      datalink_ComeDown(dl, how);
1022  }
1023}
1024
1025void
1026datalink_Down(struct datalink *dl, int how)
1027{
1028  /* Carrier is lost */
1029  switch (dl->state) {
1030    case DATALINK_OPEN:
1031      peerid_Init(&dl->peer);
1032      fsm2initial(&dl->physical->link.ccp.fsm);
1033      /* FALLTHROUGH */
1034
1035    case DATALINK_CBCP:
1036    case DATALINK_AUTH:
1037    case DATALINK_LCP:
1038      fsm2initial(&dl->physical->link.lcp.fsm);
1039      if (dl->state == DATALINK_OPENING)
1040        return;			/* we're doing a callback... */
1041      /* FALLTHROUGH */
1042
1043    default:
1044      datalink_ComeDown(dl, how);
1045  }
1046}
1047
1048void
1049datalink_StayDown(struct datalink *dl)
1050{
1051  dl->dial.tries = -1;
1052  dl->reconnect_tries = 0;
1053  dl->stayonline = 0;
1054}
1055
1056void
1057datalink_DontHangup(struct datalink *dl)
1058{
1059  dl->dial.tries = -1;
1060  dl->reconnect_tries = 0;
1061  dl->stayonline = dl->state >= DATALINK_LCP ? 1 : 0;
1062}
1063
1064int
1065datalink_Show(struct cmdargs const *arg)
1066{
1067  prompt_Printf(arg->prompt, "Name: %s\n", arg->cx->name);
1068  prompt_Printf(arg->prompt, " State:              %s\n",
1069                datalink_State(arg->cx));
1070  prompt_Printf(arg->prompt, " Peer name:          ");
1071  if (*arg->cx->peer.authname)
1072    prompt_Printf(arg->prompt, "%s\n", arg->cx->peer.authname);
1073  else if (arg->cx->state == DATALINK_OPEN)
1074    prompt_Printf(arg->prompt, "None requested\n");
1075  else
1076    prompt_Printf(arg->prompt, "N/A\n");
1077  prompt_Printf(arg->prompt, " Discriminator:      %s\n",
1078                mp_Enddisc(arg->cx->peer.enddisc.class,
1079                           arg->cx->peer.enddisc.address,
1080                           arg->cx->peer.enddisc.len));
1081
1082  prompt_Printf(arg->prompt, "\nDefaults:\n");
1083  prompt_Printf(arg->prompt, " Phone List:         %s\n",
1084                arg->cx->cfg.phone.list);
1085  if (arg->cx->cfg.dial.max)
1086    prompt_Printf(arg->prompt, " Dial tries:         %d, delay ",
1087                  arg->cx->cfg.dial.max);
1088  else
1089    prompt_Printf(arg->prompt, " Dial tries:         infinite, delay ");
1090  if (arg->cx->cfg.dial.next_timeout >= 0)
1091    prompt_Printf(arg->prompt, "%ds/", arg->cx->cfg.dial.next_timeout);
1092  else
1093    prompt_Printf(arg->prompt, "random/");
1094  if (arg->cx->cfg.dial.timeout >= 0)
1095    prompt_Printf(arg->prompt, "%ds\n", arg->cx->cfg.dial.timeout);
1096  else
1097    prompt_Printf(arg->prompt, "random\n");
1098  prompt_Printf(arg->prompt, " Reconnect tries:    %d, delay ",
1099                arg->cx->cfg.reconnect.max);
1100  if (arg->cx->cfg.reconnect.timeout > 0)
1101    prompt_Printf(arg->prompt, "%ds\n", arg->cx->cfg.reconnect.timeout);
1102  else
1103    prompt_Printf(arg->prompt, "random\n");
1104  prompt_Printf(arg->prompt, " Callback %s ", arg->cx->physical->type ==
1105                PHYS_DIRECT ?  "accepted: " : "requested:");
1106  if (!arg->cx->cfg.callback.opmask)
1107    prompt_Printf(arg->prompt, "none\n");
1108  else {
1109    int comma = 0;
1110
1111    if (arg->cx->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
1112      prompt_Printf(arg->prompt, "none");
1113      comma = 1;
1114    }
1115    if (arg->cx->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
1116      prompt_Printf(arg->prompt, "%sauth", comma ? ", " : "");
1117      comma = 1;
1118    }
1119    if (arg->cx->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
1120      prompt_Printf(arg->prompt, "%sE.164", comma ? ", " : "");
1121      if (arg->cx->physical->type != PHYS_DIRECT)
1122        prompt_Printf(arg->prompt, " (%s)", arg->cx->cfg.callback.msg);
1123      comma = 1;
1124    }
1125    if (arg->cx->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
1126      prompt_Printf(arg->prompt, "%scbcp\n", comma ? ", " : "");
1127      prompt_Printf(arg->prompt, " CBCP:               delay: %ds\n",
1128                    arg->cx->cfg.cbcp.delay);
1129      prompt_Printf(arg->prompt, "                     phone: ");
1130      if (!strcmp(arg->cx->cfg.cbcp.phone, "*")) {
1131        if (arg->cx->physical->type & PHYS_DIRECT)
1132          prompt_Printf(arg->prompt, "Caller decides\n");
1133        else
1134          prompt_Printf(arg->prompt, "Dialback server decides\n");
1135      } else
1136        prompt_Printf(arg->prompt, "%s\n", arg->cx->cfg.cbcp.phone);
1137      prompt_Printf(arg->prompt, "                     timeout: %lds\n",
1138                    arg->cx->cfg.cbcp.fsmretry);
1139    } else
1140      prompt_Printf(arg->prompt, "\n");
1141  }
1142
1143  prompt_Printf(arg->prompt, " Dial Script:        %s\n",
1144                arg->cx->cfg.script.dial);
1145  prompt_Printf(arg->prompt, " Login Script:       %s\n",
1146                arg->cx->cfg.script.login);
1147  prompt_Printf(arg->prompt, " Logout Script:      %s\n",
1148                arg->cx->cfg.script.logout);
1149  prompt_Printf(arg->prompt, " Hangup Script:      %s\n",
1150                arg->cx->cfg.script.hangup);
1151  return 0;
1152}
1153
1154int
1155datalink_SetReconnect(struct cmdargs const *arg)
1156{
1157  if (arg->argc == arg->argn+2) {
1158    arg->cx->cfg.reconnect.timeout = atoi(arg->argv[arg->argn]);
1159    arg->cx->cfg.reconnect.max = atoi(arg->argv[arg->argn+1]);
1160    return 0;
1161  }
1162  return -1;
1163}
1164
1165int
1166datalink_SetRedial(struct cmdargs const *arg)
1167{
1168  const char *sep, *osep;
1169  int timeout, inc, maxinc, tries;
1170
1171  if (arg->argc == arg->argn+1 || arg->argc == arg->argn+2) {
1172    if (strncasecmp(arg->argv[arg->argn], "random", 6) == 0 &&
1173	(arg->argv[arg->argn][6] == '\0' || arg->argv[arg->argn][6] == '.')) {
1174      arg->cx->cfg.dial.timeout = -1;
1175      randinit();
1176    } else {
1177      timeout = atoi(arg->argv[arg->argn]);
1178
1179      if (timeout >= 0)
1180	arg->cx->cfg.dial.timeout = timeout;
1181      else {
1182	log_Printf(LogWARN, "Invalid redial timeout\n");
1183	return -1;
1184      }
1185    }
1186
1187    sep = strchr(arg->argv[arg->argn], '+');
1188    if (sep) {
1189      inc = atoi(++sep);
1190      osep = sep;
1191      if (inc >= 0)
1192        arg->cx->cfg.dial.inc = inc;
1193      else {
1194        log_Printf(LogWARN, "Invalid timeout increment\n");
1195        return -1;
1196      }
1197      sep = strchr(sep, '-');
1198      if (sep) {
1199        maxinc = atoi(++sep);
1200        if (maxinc >= 0)
1201          arg->cx->cfg.dial.maxinc = maxinc;
1202        else {
1203          log_Printf(LogWARN, "Invalid maximum timeout increments\n");
1204          return -1;
1205        }
1206      } else {
1207        /* Default timeout increment */
1208        arg->cx->cfg.dial.maxinc = 10;
1209        sep = osep;
1210      }
1211    } else {
1212      /* Default timeout increment & max increment */
1213      arg->cx->cfg.dial.inc = 0;
1214      arg->cx->cfg.dial.maxinc = 10;
1215      sep = arg->argv[arg->argn];
1216    }
1217
1218    sep = strchr(sep, '.');
1219    if (sep) {
1220      if (strcasecmp(++sep, "random") == 0) {
1221	arg->cx->cfg.dial.next_timeout = -1;
1222	randinit();
1223      } else {
1224	timeout = atoi(sep);
1225	if (timeout >= 0)
1226	  arg->cx->cfg.dial.next_timeout = timeout;
1227	else {
1228	  log_Printf(LogWARN, "Invalid next redial timeout\n");
1229	  return -1;
1230	}
1231      }
1232    } else
1233      /* Default next timeout */
1234      arg->cx->cfg.dial.next_timeout = DIAL_NEXT_TIMEOUT;
1235
1236    if (arg->argc == arg->argn+2) {
1237      tries = atoi(arg->argv[arg->argn+1]);
1238
1239      if (tries >= 0) {
1240	arg->cx->cfg.dial.max = tries;
1241      } else {
1242	log_Printf(LogWARN, "Invalid retry value\n");
1243	return 1;
1244      }
1245    }
1246    return 0;
1247  }
1248
1249  return -1;
1250}
1251
1252static const char * const states[] = {
1253  "closed",
1254  "opening",
1255  "hangup",
1256  "dial",
1257  "carrier",
1258  "logout",
1259  "login",
1260  "ready",
1261  "lcp",
1262  "auth",
1263  "cbcp",
1264  "open"
1265};
1266
1267const char *
1268datalink_State(struct datalink *dl)
1269{
1270  if (dl->state < 0 || dl->state >= sizeof states / sizeof states[0])
1271    return "unknown";
1272  return states[dl->state];
1273}
1274
1275static void
1276datalink_NewState(struct datalink *dl, int state)
1277{
1278  if (state != dl->state) {
1279    if (state >= 0 && state < sizeof states / sizeof states[0]) {
1280      log_Printf(LogPHASE, "%s: %s -> %s\n", dl->name, datalink_State(dl),
1281                 states[state]);
1282      dl->state = state;
1283    } else
1284      log_Printf(LogERROR, "%s: Can't enter state %d !\n", dl->name, state);
1285  }
1286}
1287
1288struct datalink *
1289iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov,
1290             int fd, int *auxfd, int *nauxfd)
1291{
1292  struct datalink *dl, *cdl;
1293  struct fsm_retry copy;
1294  char *oname;
1295
1296  dl = (struct datalink *)iov[(*niov)++].iov_base;
1297  dl->name = iov[*niov].iov_base;
1298
1299  if (dl->name[DATALINK_MAXNAME-1]) {
1300    dl->name[DATALINK_MAXNAME-1] = '\0';
1301    if (strlen(dl->name) == DATALINK_MAXNAME - 1)
1302      log_Printf(LogWARN, "Datalink name truncated to \"%s\"\n", dl->name);
1303  }
1304
1305  /* Make sure the name is unique ! */
1306  oname = NULL;
1307  do {
1308    for (cdl = bundle->links; cdl; cdl = cdl->next)
1309      if (!strcasecmp(dl->name, cdl->name)) {
1310        if (oname)
1311          free(datalink_NextName(dl));
1312        else
1313          oname = datalink_NextName(dl);
1314        break;	/* Keep renaming 'till we have no conflicts */
1315      }
1316  } while (cdl);
1317
1318  if (oname) {
1319    log_Printf(LogPHASE, "Rename link %s to %s\n", oname, dl->name);
1320    free(oname);
1321  } else {
1322    dl->name = strdup(dl->name);
1323    free(iov[*niov].iov_base);
1324  }
1325  (*niov)++;
1326
1327  dl->desc.type = DATALINK_DESCRIPTOR;
1328  dl->desc.UpdateSet = datalink_UpdateSet;
1329  dl->desc.IsSet = datalink_IsSet;
1330  dl->desc.Read = datalink_Read;
1331  dl->desc.Write = datalink_Write;
1332
1333  mp_linkInit(&dl->mp);
1334  *dl->phone.list = '\0';
1335  dl->phone.next = NULL;
1336  dl->phone.alt = NULL;
1337  dl->phone.chosen = "N/A";
1338
1339  dl->bundle = bundle;
1340  dl->next = NULL;
1341  memset(&dl->dial.timer, '\0', sizeof dl->dial.timer);
1342  dl->dial.tries = 0;
1343  dl->reconnect_tries = 0;
1344  dl->parent = &bundle->fsm;
1345  dl->fsmp.LayerStart = datalink_LayerStart;
1346  dl->fsmp.LayerUp = datalink_LayerUp;
1347  dl->fsmp.LayerDown = datalink_LayerDown;
1348  dl->fsmp.LayerFinish = datalink_LayerFinish;
1349  dl->fsmp.object = dl;
1350
1351  dl->physical = iov2physical(dl, iov, niov, maxiov, fd, auxfd, nauxfd);
1352
1353  if (!dl->physical) {
1354    free(dl->name);
1355    free(dl);
1356    dl = NULL;
1357  } else {
1358    copy = dl->pap.cfg.fsm;
1359    pap_Init(&dl->pap, dl->physical);
1360    dl->pap.cfg.fsm = copy;
1361
1362    copy = dl->chap.auth.cfg.fsm;
1363    chap_Init(&dl->chap, dl->physical);
1364    dl->chap.auth.cfg.fsm = copy;
1365
1366    cbcp_Init(&dl->cbcp, dl->physical);
1367
1368    memset(&dl->chat, '\0', sizeof dl->chat);	/* Force buf{start,end} reset */
1369    chat_Init(&dl->chat, dl->physical);
1370
1371    log_Printf(LogPHASE, "%s: Transferred in %s state\n",
1372              dl->name, datalink_State(dl));
1373  }
1374
1375  return dl;
1376}
1377
1378int
1379datalink2iov(struct datalink *dl, struct iovec *iov, int *niov, int maxiov,
1380             int *auxfd, int *nauxfd)
1381{
1382  /* If `dl' is NULL, we're allocating before a Fromiov() */
1383  int link_fd;
1384
1385  if (dl) {
1386    timer_Stop(&dl->dial.timer);
1387    /* The following is purely for the sake of paranoia */
1388    cbcp_Down(&dl->cbcp);
1389    timer_Stop(&dl->pap.authtimer);
1390    timer_Stop(&dl->chap.auth.authtimer);
1391  }
1392
1393  if (*niov >= maxiov - 1) {
1394    log_Printf(LogERROR, "Toiov: No room for datalink !\n");
1395    if (dl) {
1396      free(dl->name);
1397      free(dl);
1398    }
1399    return -1;
1400  }
1401
1402  iov[*niov].iov_base = (void *)dl;
1403  iov[(*niov)++].iov_len = sizeof *dl;
1404  iov[*niov].iov_base = dl ? realloc(dl->name, DATALINK_MAXNAME) : NULL;
1405  iov[(*niov)++].iov_len = DATALINK_MAXNAME;
1406
1407  link_fd = physical2iov(dl ? dl->physical : NULL, iov, niov, maxiov, auxfd,
1408                         nauxfd);
1409
1410  if (link_fd == -1 && dl) {
1411    free(dl->name);
1412    free(dl);
1413  }
1414
1415  return link_fd;
1416}
1417
1418void
1419datalink_Rename(struct datalink *dl, const char *name)
1420{
1421  free(dl->name);
1422  dl->physical->link.name = dl->name = strdup(name);
1423}
1424
1425char *
1426datalink_NextName(struct datalink *dl)
1427{
1428  int f, n;
1429  char *name, *oname;
1430
1431  n = strlen(dl->name);
1432  name = (char *)malloc(n+3);
1433  for (f = n - 1; f >= 0; f--)
1434    if (!isdigit(dl->name[f]))
1435      break;
1436  n = sprintf(name, "%.*s-", dl->name[f] == '-' ? f : f + 1, dl->name);
1437  sprintf(name + n, "%d", atoi(dl->name + f + 1) + 1);
1438  oname = dl->name;
1439  dl->name = name;
1440  /* our physical link name isn't updated (it probably isn't created yet) */
1441  return oname;
1442}
1443
1444int
1445datalink_SetMode(struct datalink *dl, int mode)
1446{
1447  if (!physical_SetMode(dl->physical, mode))
1448    return 0;
1449  if (dl->physical->type & (PHYS_DIRECT|PHYS_DEDICATED))
1450    dl->script.run = 0;
1451  if (dl->physical->type == PHYS_DIRECT)
1452    dl->reconnect_tries = 0;
1453  if (mode & (PHYS_DDIAL|PHYS_BACKGROUND|PHYS_FOREGROUND) &&
1454      dl->state <= DATALINK_READY)
1455    datalink_Up(dl, 1, 1);
1456  return 1;
1457}
1458
1459int
1460datalink_GetDialTimeout(struct datalink *dl)
1461{
1462  int result = dl->cfg.dial.timeout + dl->dial.incs * dl->cfg.dial.inc;
1463
1464  if (dl->dial.incs < dl->cfg.dial.maxinc)
1465    dl->dial.incs++;
1466
1467  return result;
1468}
1469