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