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