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