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