]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ppp/datalink.c
This commit was generated by cvs2svn to compensate for changes in r101386,
[FreeBSD/FreeBSD.git] / usr.sbin / ppp / datalink.c
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$
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
80 static void datalink_LoginDone(struct datalink *);
81 static void datalink_NewState(struct datalink *, int);
82
83 static void
84 datalink_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
93 static int
94 datalink_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
112 static void
113 datalink_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
186 const char *
187 datalink_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
208 static void
209 datalink_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
248 static int
249 datalink_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       /* fall through */
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
412 int
413 datalink_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
418 static int
419 datalink_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
445 static void
446 datalink_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
475 static int
476 datalink_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
524 void
525 datalink_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
557 static void
558 datalink_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
567 static void
568 datalink_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
594 static void
595 datalink_AuthReInit(struct datalink *dl)
596 {
597   auth_StopTimer(&dl->pap);
598   auth_StopTimer(&dl->chap.auth);
599   chap_ReInit(&dl->chap);
600 }
601
602 void
603 datalink_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
609 void
610 datalink_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         /* fall through */
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
655 void
656 datalink_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
663 void
664 datalink_CBCPFailed(struct datalink *dl)
665 {
666   cbcp_Down(&dl->cbcp);
667   datalink_CBCPComplete(dl);
668 }
669
670 void
671 datalink_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
738 void
739 datalink_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
746 static void
747 datalink_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         /* fall through (just in case) */
760
761       case DATALINK_CBCP:
762         if (!dl->cbcp.required)
763           cbcp_Down(&dl->cbcp);
764         /* fall through (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
775 static void
776 datalink_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
789 struct datalink *
790 datalink_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
869 struct datalink *
870 datalink_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
933 struct datalink *
934 datalink_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
960 void
961 datalink_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       /* fall through */
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
999 void
1000 datalink_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       /* fall through */
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
1025 void
1026 datalink_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       /* fall through */
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       /* fall through */
1042
1043     default:
1044       datalink_ComeDown(dl, how);
1045   }
1046 }
1047
1048 void
1049 datalink_StayDown(struct datalink *dl)
1050 {
1051   dl->dial.tries = -1;
1052   dl->reconnect_tries = 0;
1053   dl->stayonline = 0;
1054 }
1055
1056 void
1057 datalink_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
1064 int
1065 datalink_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
1154 int
1155 datalink_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
1165 int
1166 datalink_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
1252 static 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
1267 const char *
1268 datalink_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
1275 static void
1276 datalink_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
1288 struct datalink *
1289 iov2datalink(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
1378 int
1379 datalink2iov(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
1418 void
1419 datalink_Rename(struct datalink *dl, const char *name)
1420 {
1421   free(dl->name);
1422   dl->physical->link.name = dl->name = strdup(name);
1423 }
1424
1425 char *
1426 datalink_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
1444 int
1445 datalink_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
1459 int
1460 datalink_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 }