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