bundle.c revision 36312
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: bundle.c,v 1.2 1998/05/21 21:44:08 brian Exp $ 27 */ 28 29#include <sys/types.h> 30#include <sys/socket.h> 31#include <netinet/in.h> 32#include <net/if.h> 33#include <arpa/inet.h> 34#include <net/route.h> 35#include <net/if_dl.h> 36#include <netinet/in_systm.h> 37#include <netinet/ip.h> 38#include <net/if_tun.h> 39#include <sys/un.h> 40 41#include <errno.h> 42#include <fcntl.h> 43#include <paths.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <sys/ioctl.h> 48#include <sys/uio.h> 49#include <termios.h> 50#include <unistd.h> 51 52#include "command.h" 53#include "mbuf.h" 54#include "log.h" 55#include "id.h" 56#include "defs.h" 57#include "timer.h" 58#include "fsm.h" 59#include "iplist.h" 60#include "lqr.h" 61#include "hdlc.h" 62#include "throughput.h" 63#include "slcompress.h" 64#include "ipcp.h" 65#include "filter.h" 66#include "descriptor.h" 67#include "route.h" 68#include "lcp.h" 69#include "ccp.h" 70#include "link.h" 71#include "mp.h" 72#include "bundle.h" 73#include "async.h" 74#include "physical.h" 75#include "modem.h" 76#include "loadalias.h" 77#include "auth.h" 78#include "lcpproto.h" 79#include "chap.h" 80#include "tun.h" 81#include "prompt.h" 82#include "chat.h" 83#include "datalink.h" 84#include "ip.h" 85 86#define SCATTER_SEGMENTS 4 /* version, datalink, name, physical */ 87#define SOCKET_OVERHEAD 100 /* additional buffer space for large */ 88 /* {recv,send}msg() calls */ 89 90static int bundle_RemainingIdleTime(struct bundle *); 91static int bundle_RemainingAutoLoadTime(struct bundle *); 92 93static const char *PhaseNames[] = { 94 "Dead", "Establish", "Authenticate", "Network", "Terminate" 95}; 96 97const char * 98bundle_PhaseName(struct bundle *bundle) 99{ 100 return bundle->phase <= PHASE_TERMINATE ? 101 PhaseNames[bundle->phase] : "unknown"; 102} 103 104void 105bundle_NewPhase(struct bundle *bundle, u_int new) 106{ 107 if (new == bundle->phase) 108 return; 109 110 if (new <= PHASE_TERMINATE) 111 log_Printf(LogPHASE, "bundle: %s\n", PhaseNames[new]); 112 113 switch (new) { 114 case PHASE_DEAD: 115 bundle->phase = new; 116 break; 117 118 case PHASE_ESTABLISH: 119 bundle->phase = new; 120 break; 121 122 case PHASE_AUTHENTICATE: 123 bundle->phase = new; 124 bundle_DisplayPrompt(bundle); 125 break; 126 127 case PHASE_NETWORK: 128 ipcp_Setup(&bundle->ncp.ipcp); 129 fsm_Up(&bundle->ncp.ipcp.fsm); 130 fsm_Open(&bundle->ncp.ipcp.fsm); 131 bundle->phase = new; 132 bundle_DisplayPrompt(bundle); 133 break; 134 135 case PHASE_TERMINATE: 136 bundle->phase = new; 137 mp_Down(&bundle->ncp.mp); 138 bundle_DisplayPrompt(bundle); 139 break; 140 } 141} 142 143static int 144bundle_CleanInterface(const struct bundle *bundle) 145{ 146 int s; 147 struct ifreq ifrq; 148 struct ifaliasreq ifra; 149 150 s = ID0socket(AF_INET, SOCK_DGRAM, 0); 151 if (s < 0) { 152 log_Printf(LogERROR, "bundle_CleanInterface: socket(): %s\n", 153 strerror(errno)); 154 return (-1); 155 } 156 strncpy(ifrq.ifr_name, bundle->ifp.Name, sizeof ifrq.ifr_name - 1); 157 ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; 158 while (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0) { 159 memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask); 160 strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1); 161 ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 162 ifra.ifra_addr = ifrq.ifr_addr; 163 if (ID0ioctl(s, SIOCGIFDSTADDR, &ifrq) < 0) { 164 if (ifra.ifra_addr.sa_family == AF_INET) 165 log_Printf(LogERROR, 166 "bundle_CleanInterface: Can't get dst for %s on %s !\n", 167 inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr), 168 bundle->ifp.Name); 169 close(s); 170 return 0; 171 } 172 ifra.ifra_broadaddr = ifrq.ifr_dstaddr; 173 if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) { 174 if (ifra.ifra_addr.sa_family == AF_INET) 175 log_Printf(LogERROR, 176 "bundle_CleanInterface: Can't delete %s address on %s !\n", 177 inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr), 178 bundle->ifp.Name); 179 close(s); 180 return 0; 181 } 182 } 183 close(s); 184 185 return 1; 186} 187 188static void 189bundle_LayerStart(void *v, struct fsm *fp) 190{ 191 /* The given FSM is about to start up ! */ 192} 193 194 195static void 196bundle_Notify(struct bundle *bundle, char c) 197{ 198 if (bundle->notify.fd != -1) { 199 if (write(bundle->notify.fd, &c, 1) == 1) 200 log_Printf(LogPHASE, "Parent notified of success.\n"); 201 else 202 log_Printf(LogPHASE, "Failed to notify parent of success.\n"); 203 close(bundle->notify.fd); 204 bundle->notify.fd = -1; 205 } 206} 207 208static void 209bundle_AutoLoadTimeout(void *v) 210{ 211 struct bundle *bundle = (struct bundle *)v; 212 213 if (bundle->autoload.comingup) { 214 log_Printf(LogPHASE, "autoload: Another link is required\n"); 215 /* bundle_Open() stops the timer */ 216 bundle_Open(bundle, NULL, PHYS_DEMAND); 217 } else { 218 struct datalink *dl, *last; 219 220 timer_Stop(&bundle->autoload.timer); 221 for (last = NULL, dl = bundle->links; dl; dl = dl->next) 222 if (dl->physical->type == PHYS_DEMAND && dl->state == DATALINK_OPEN) 223 last = dl; 224 225 if (last) 226 datalink_Close(last, 1); 227 } 228} 229 230static void 231bundle_StartAutoLoadTimer(struct bundle *bundle, int up) 232{ 233 struct datalink *dl; 234 235 timer_Stop(&bundle->autoload.timer); 236 237 if (bundle->CleaningUp || bundle->phase != PHASE_NETWORK) { 238 dl = NULL; 239 bundle->autoload.running = 0; 240 } else if (up) { 241 for (dl = bundle->links; dl; dl = dl->next) 242 if (dl->state == DATALINK_CLOSED && dl->physical->type == PHYS_DEMAND) { 243 if (bundle->cfg.autoload.max.timeout) { 244 bundle->autoload.timer.func = bundle_AutoLoadTimeout; 245 bundle->autoload.timer.name = "autoload up"; 246 bundle->autoload.timer.load = 247 bundle->cfg.autoload.max.timeout * SECTICKS; 248 bundle->autoload.timer.arg = bundle; 249 timer_Start(&bundle->autoload.timer); 250 bundle->autoload.done = time(NULL) + bundle->cfg.autoload.max.timeout; 251 } else 252 bundle_AutoLoadTimeout(bundle); 253 break; 254 } 255 bundle->autoload.running = (dl || bundle->cfg.autoload.min.timeout) ? 1 : 0; 256 } else { 257 int nlinks; 258 struct datalink *adl; 259 260 for (nlinks = 0, adl = NULL, dl = bundle->links; dl; dl = dl->next) 261 if (dl->state == DATALINK_OPEN) { 262 if (dl->physical->type == PHYS_DEMAND) 263 adl = dl; 264 if (++nlinks > 1 && adl) { 265 if (bundle->cfg.autoload.min.timeout) { 266 bundle->autoload.timer.func = bundle_AutoLoadTimeout; 267 bundle->autoload.timer.name = "autoload down"; 268 bundle->autoload.timer.load = 269 bundle->cfg.autoload.min.timeout * SECTICKS; 270 bundle->autoload.timer.arg = bundle; 271 timer_Start(&bundle->autoload.timer); 272 bundle->autoload.done = 273 time(NULL) + bundle->cfg.autoload.min.timeout; 274 } 275 break; 276 } 277 } 278 279 bundle->autoload.running = 1; 280 } 281 282 bundle->autoload.comingup = up ? 1 : 0; 283} 284 285static void 286bundle_StopAutoLoadTimer(struct bundle *bundle) 287{ 288 timer_Stop(&bundle->autoload.timer); 289 bundle->autoload.done = 0; 290} 291 292static int 293bundle_RemainingAutoLoadTime(struct bundle *bundle) 294{ 295 if (bundle->autoload.done) 296 return bundle->autoload.done - time(NULL); 297 return -1; 298} 299 300 301static void 302bundle_LayerUp(void *v, struct fsm *fp) 303{ 304 /* 305 * The given fsm is now up 306 * If it's an LCP set our mtu (if we're multilink, add up the link 307 * speeds and set the MRRU) and start our autoload timer. 308 * If it's an NCP, tell our -background parent to go away. 309 * If it's the first NCP, start the idle timer. 310 */ 311 struct bundle *bundle = (struct bundle *)v; 312 313 if (fp->proto == PROTO_LCP) { 314 if (bundle->ncp.mp.active) { 315 struct datalink *dl; 316 317 bundle->ifp.Speed = 0; 318 for (dl = bundle->links; dl; dl = dl->next) 319 if (dl->state == DATALINK_OPEN) 320 bundle->ifp.Speed += modem_Speed(dl->physical); 321 tun_configure(bundle, bundle->ncp.mp.peer_mrru); 322 bundle->autoload.running = 1; 323 } else { 324 bundle->ifp.Speed = modem_Speed(link2physical(fp->link)); 325 tun_configure(bundle, fsm2lcp(fp)->his_mru); 326 } 327 } else if (fp->proto == PROTO_IPCP) { 328 bundle_StartIdleTimer(bundle); 329 bundle_Notify(bundle, EX_NORMAL); 330 } 331} 332 333static void 334bundle_LayerDown(void *v, struct fsm *fp) 335{ 336 /* 337 * The given FSM has been told to come down. 338 * If it's our last NCP, stop the idle timer. 339 * If it's an LCP and we're in multilink mode, adjust our tun 340 * speed and make sure our minimum sequence number is adjusted. 341 */ 342 343 struct bundle *bundle = (struct bundle *)v; 344 345 if (fp->proto == PROTO_IPCP) 346 bundle_StopIdleTimer(bundle); 347 else if (fp->proto == PROTO_LCP && bundle->ncp.mp.active) { 348 struct datalink *dl; 349 struct datalink *lost; 350 351 bundle->ifp.Speed = 0; 352 lost = NULL; 353 for (dl = bundle->links; dl; dl = dl->next) 354 if (fp == &dl->physical->link.lcp.fsm) 355 lost = dl; 356 else if (dl->state == DATALINK_OPEN) 357 bundle->ifp.Speed += modem_Speed(dl->physical); 358 359 if (bundle->ifp.Speed) 360 /* Don't configure down to a speed of 0 */ 361 tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru); 362 363 if (lost) 364 mp_LinkLost(&bundle->ncp.mp, lost); 365 else 366 log_Printf(LogERROR, "Oops, lost an unrecognised datalink (%s) !\n", 367 fp->link->name); 368 } 369} 370 371static void 372bundle_LayerFinish(void *v, struct fsm *fp) 373{ 374 /* The given fsm is now down (fp cannot be NULL) 375 * 376 * If it's the last LCP, fsm_Down all NCPs 377 * If it's the last NCP, fsm_Close all LCPs 378 */ 379 380 struct bundle *bundle = (struct bundle *)v; 381 struct datalink *dl; 382 383 if (fp->proto == PROTO_IPCP) { 384 if (bundle_Phase(bundle) != PHASE_DEAD) 385 bundle_NewPhase(bundle, PHASE_TERMINATE); 386 for (dl = bundle->links; dl; dl = dl->next) 387 datalink_Close(dl, 0); 388 fsm_Down(fp); 389 fsm_Close(fp); 390 } else if (fp->proto == PROTO_LCP) { 391 int others_active; 392 393 others_active = 0; 394 for (dl = bundle->links; dl; dl = dl->next) 395 if (fp != &dl->physical->link.lcp.fsm && 396 dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) 397 others_active++; 398 399 if (!others_active) { 400 fsm_Down(&bundle->ncp.ipcp.fsm); 401 fsm_Close(&bundle->ncp.ipcp.fsm); /* ST_INITIAL please */ 402 } 403 } 404} 405 406int 407bundle_LinkIsUp(const struct bundle *bundle) 408{ 409 return bundle->ncp.ipcp.fsm.state == ST_OPENED; 410} 411 412void 413bundle_Close(struct bundle *bundle, const char *name, int staydown) 414{ 415 /* 416 * Please close the given datalink. 417 * If name == NULL or name is the last datalink, fsm_Close all NCPs 418 * (except our MP) 419 * If it isn't the last datalink, just Close that datalink. 420 */ 421 422 struct datalink *dl, *this_dl; 423 int others_active; 424 425 if (bundle->phase == PHASE_TERMINATE || bundle->phase == PHASE_DEAD) 426 return; 427 428 others_active = 0; 429 this_dl = NULL; 430 431 for (dl = bundle->links; dl; dl = dl->next) { 432 if (name && !strcasecmp(name, dl->name)) 433 this_dl = dl; 434 if (name == NULL || this_dl == dl) { 435 if (staydown) 436 datalink_StayDown(dl); 437 } else if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) 438 others_active++; 439 } 440 441 if (name && this_dl == NULL) { 442 log_Printf(LogWARN, "%s: Invalid datalink name\n", name); 443 return; 444 } 445 446 if (!others_active) { 447 bundle_StopIdleTimer(bundle); 448 bundle_StopAutoLoadTimer(bundle); 449 if (bundle->ncp.ipcp.fsm.state > ST_CLOSED || 450 bundle->ncp.ipcp.fsm.state == ST_STARTING) 451 fsm_Close(&bundle->ncp.ipcp.fsm); 452 else { 453 if (bundle->ncp.ipcp.fsm.state > ST_INITIAL) { 454 fsm_Close(&bundle->ncp.ipcp.fsm); 455 fsm_Down(&bundle->ncp.ipcp.fsm); 456 } 457 for (dl = bundle->links; dl; dl = dl->next) 458 datalink_Close(dl, staydown); 459 } 460 } else if (this_dl && this_dl->state != DATALINK_CLOSED && 461 this_dl->state != DATALINK_HANGUP) 462 datalink_Close(this_dl, staydown); 463} 464 465void 466bundle_Down(struct bundle *bundle) 467{ 468 struct datalink *dl; 469 470 for (dl = bundle->links; dl; dl = dl->next) 471 datalink_Down(dl, 1); 472} 473 474static int 475bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 476{ 477 struct bundle *bundle = descriptor2bundle(d); 478 struct datalink *dl; 479 struct descriptor *desc; 480 int result, want, queued, nlinks; 481 482 result = 0; 483 for (dl = bundle->links; dl; dl = dl->next) 484 result += descriptor_UpdateSet(&dl->desc, r, w, e, n); 485 486 for (desc = bundle->desc.next; desc; desc = desc->next) 487 result += descriptor_UpdateSet(desc, r, w, e, n); 488 489 /* If there are aren't many packets queued, look for some more. */ 490 for (nlinks = 0, dl = bundle->links; dl; dl = dl->next) 491 nlinks++; 492 493 if (nlinks) { 494 queued = r ? bundle_FillQueues(bundle) : ip_QueueLen(); 495 if (bundle->autoload.running) { 496 if (queued < bundle->cfg.autoload.max.packets) { 497 if (queued > bundle->cfg.autoload.min.packets) 498 bundle_StopAutoLoadTimer(bundle); 499 else if (bundle->autoload.timer.state != TIMER_RUNNING || 500 bundle->autoload.comingup) 501 bundle_StartAutoLoadTimer(bundle, 0); 502 } else if (bundle->autoload.timer.state != TIMER_RUNNING || 503 !bundle->autoload.comingup) 504 bundle_StartAutoLoadTimer(bundle, 1); 505 } 506 507 if (r) { 508 /* enough surplus so that we can tell if we're getting swamped */ 509 want = bundle->cfg.autoload.max.packets + nlinks * 2; 510 /* but at least 20 packets ! */ 511 if (want < 20) 512 want = 20; 513 if (queued < want) { 514 /* Not enough - select() for more */ 515 FD_SET(bundle->dev.fd, r); 516 if (*n < bundle->dev.fd + 1) 517 *n = bundle->dev.fd + 1; 518 log_Printf(LogTIMER, "tun: fdset(r) %d\n", bundle->dev.fd); 519 result++; 520 } 521 } 522 } 523 524 /* 525 * This *MUST* be called after the datalink UpdateSet()s as it 526 * might be ``holding'' one of the datalinks (death-row) and 527 * wants to be able to de-select() it from the descriptor set. 528 */ 529 descriptor_UpdateSet(&bundle->ncp.mp.server.desc, r, w, e, n); 530 531 return result; 532} 533 534static int 535bundle_IsSet(struct descriptor *d, const fd_set *fdset) 536{ 537 struct bundle *bundle = descriptor2bundle(d); 538 struct datalink *dl; 539 struct descriptor *desc; 540 541 for (dl = bundle->links; dl; dl = dl->next) 542 if (descriptor_IsSet(&dl->desc, fdset)) 543 return 1; 544 545 for (desc = bundle->desc.next; desc; desc = desc->next) 546 if (descriptor_IsSet(desc, fdset)) 547 return 1; 548 549 if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset)) 550 return 1; 551 552 return FD_ISSET(bundle->dev.fd, fdset); 553} 554 555static void 556bundle_DescriptorRead(struct descriptor *d, struct bundle *bundle, 557 const fd_set *fdset) 558{ 559 struct datalink *dl; 560 struct descriptor *desc; 561 562 if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset)) 563 descriptor_Read(&bundle->ncp.mp.server.desc, bundle, fdset); 564 565 for (dl = bundle->links; dl; dl = dl->next) 566 if (descriptor_IsSet(&dl->desc, fdset)) 567 descriptor_Read(&dl->desc, bundle, fdset); 568 569 for (desc = bundle->desc.next; desc; desc = desc->next) 570 if (descriptor_IsSet(desc, fdset)) 571 descriptor_Read(desc, bundle, fdset); 572 573 if (FD_ISSET(bundle->dev.fd, fdset)) { 574 struct tun_data tun; 575 int n, pri; 576 577 /* something to read from tun */ 578 n = read(bundle->dev.fd, &tun, sizeof tun); 579 if (n < 0) { 580 log_Printf(LogERROR, "read from tun: %s\n", strerror(errno)); 581 return; 582 } 583 n -= sizeof tun - sizeof tun.data; 584 if (n <= 0) { 585 log_Printf(LogERROR, "read from tun: Only %d bytes read\n", n); 586 return; 587 } 588 if (!tun_check_header(tun, AF_INET)) 589 return; 590 591 if (((struct ip *)tun.data)->ip_dst.s_addr == 592 bundle->ncp.ipcp.my_ip.s_addr) { 593 /* we've been asked to send something addressed *to* us :( */ 594 if (Enabled(bundle, OPT_LOOPBACK)) { 595 pri = PacketCheck(bundle, tun.data, n, &bundle->filter.in); 596 if (pri >= 0) { 597 struct mbuf *bp; 598 599#ifndef NOALIAS 600 if (alias_IsEnabled()) { 601 (*PacketAlias.In)(tun.data, sizeof tun.data); 602 n = ntohs(((struct ip *)tun.data)->ip_len); 603 } 604#endif 605 bp = mbuf_Alloc(n, MB_IPIN); 606 memcpy(MBUF_CTOP(bp), tun.data, n); 607 ip_Input(bundle, bp); 608 log_Printf(LogDEBUG, "Looped back packet addressed to myself\n"); 609 } 610 return; 611 } else 612 log_Printf(LogDEBUG, "Oops - forwarding packet addressed to myself\n"); 613 } 614 615 /* 616 * Process on-demand dialup. Output packets are queued within tunnel 617 * device until IPCP is opened. 618 */ 619 620 if (bundle_Phase(bundle) == PHASE_DEAD) { 621 /* 622 * Note, we must be in AUTO mode :-/ otherwise our interface should 623 * *not* be UP and we can't receive data 624 */ 625 if ((pri = PacketCheck(bundle, tun.data, n, &bundle->filter.dial)) >= 0) 626 bundle_Open(bundle, NULL, PHYS_DEMAND); 627 else 628 /* 629 * Drop the packet. If we were to queue it, we'd just end up with 630 * a pile of timed-out data in our output queue by the time we get 631 * around to actually dialing. We'd also prematurely reach the 632 * threshold at which we stop select()ing to read() the tun 633 * device - breaking auto-dial. 634 */ 635 return; 636 } 637 638 pri = PacketCheck(bundle, tun.data, n, &bundle->filter.out); 639 if (pri >= 0) { 640#ifndef NOALIAS 641 if (alias_IsEnabled()) { 642 (*PacketAlias.Out)(tun.data, sizeof tun.data); 643 n = ntohs(((struct ip *)tun.data)->ip_len); 644 } 645#endif 646 ip_Enqueue(pri, tun.data, n); 647 } 648 } 649} 650 651static void 652bundle_DescriptorWrite(struct descriptor *d, struct bundle *bundle, 653 const fd_set *fdset) 654{ 655 struct datalink *dl; 656 struct descriptor *desc; 657 658 /* This is not actually necessary as struct mpserver doesn't Write() */ 659 if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset)) 660 descriptor_Write(&bundle->ncp.mp.server.desc, bundle, fdset); 661 662 for (dl = bundle->links; dl; dl = dl->next) 663 if (descriptor_IsSet(&dl->desc, fdset)) 664 descriptor_Write(&dl->desc, bundle, fdset); 665 666 for (desc = bundle->desc.next; desc; desc = desc->next) 667 if (descriptor_IsSet(desc, fdset)) 668 descriptor_Write(desc, bundle, fdset); 669} 670 671 672struct bundle * 673bundle_Create(const char *prefix, struct prompt *prompt, int type) 674{ 675 int s, enoentcount, err; 676 struct ifreq ifrq; 677 static struct bundle bundle; /* there can be only one */ 678 679 if (bundle.ifp.Name != NULL) { /* Already allocated ! */ 680 log_Printf(LogERROR, "bundle_Create: There's only one BUNDLE !\n"); 681 return NULL; 682 } 683 684 err = ENOENT; 685 enoentcount = 0; 686 for (bundle.unit = 0; ; bundle.unit++) { 687 snprintf(bundle.dev.Name, sizeof bundle.dev.Name, "%s%d", 688 prefix, bundle.unit); 689 bundle.dev.fd = ID0open(bundle.dev.Name, O_RDWR); 690 if (bundle.dev.fd >= 0) 691 break; 692 else if (errno == ENXIO) { 693 err = errno; 694 break; 695 } else if (errno == ENOENT) { 696 if (++enoentcount > 2) 697 break; 698 } else 699 err = errno; 700 } 701 702 if (bundle.dev.fd < 0) { 703 log_Printf(LogWARN, "No available tunnel devices found (%s).\n", 704 strerror(err)); 705 return NULL; 706 } 707 708 log_SetTun(bundle.unit); 709 710 s = socket(AF_INET, SOCK_DGRAM, 0); 711 if (s < 0) { 712 log_Printf(LogERROR, "bundle_Create: socket(): %s\n", strerror(errno)); 713 close(bundle.dev.fd); 714 return NULL; 715 } 716 717 bundle.ifp.Name = strrchr(bundle.dev.Name, '/'); 718 if (bundle.ifp.Name == NULL) 719 bundle.ifp.Name = bundle.dev.Name; 720 else 721 bundle.ifp.Name++; 722 723 /* 724 * Now, bring up the interface. 725 */ 726 memset(&ifrq, '\0', sizeof ifrq); 727 strncpy(ifrq.ifr_name, bundle.ifp.Name, sizeof ifrq.ifr_name - 1); 728 ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; 729 if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { 730 log_Printf(LogERROR, "OpenTunnel: ioctl(SIOCGIFFLAGS): %s\n", 731 strerror(errno)); 732 close(s); 733 close(bundle.dev.fd); 734 bundle.ifp.Name = NULL; 735 return NULL; 736 } 737 ifrq.ifr_flags |= IFF_UP; 738 if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { 739 log_Printf(LogERROR, "OpenTunnel: ioctl(SIOCSIFFLAGS): %s\n", 740 strerror(errno)); 741 close(s); 742 close(bundle.dev.fd); 743 bundle.ifp.Name = NULL; 744 return NULL; 745 } 746 747 close(s); 748 749 if ((bundle.ifp.Index = GetIfIndex(bundle.ifp.Name)) < 0) { 750 log_Printf(LogERROR, "OpenTunnel: Can't find interface index.\n"); 751 close(bundle.dev.fd); 752 bundle.ifp.Name = NULL; 753 return NULL; 754 } 755 prompt_Printf(prompt, "Using interface: %s\n", bundle.ifp.Name); 756 log_Printf(LogPHASE, "Using interface: %s\n", bundle.ifp.Name); 757 758 bundle.ifp.Speed = 0; 759 760 bundle.routing_seq = 0; 761 bundle.phase = PHASE_DEAD; 762 bundle.CleaningUp = 0; 763 764 bundle.fsm.LayerStart = bundle_LayerStart; 765 bundle.fsm.LayerUp = bundle_LayerUp; 766 bundle.fsm.LayerDown = bundle_LayerDown; 767 bundle.fsm.LayerFinish = bundle_LayerFinish; 768 bundle.fsm.object = &bundle; 769 770 bundle.cfg.idle_timeout = NCP_IDLE_TIMEOUT; 771 *bundle.cfg.auth.name = '\0'; 772 *bundle.cfg.auth.key = '\0'; 773 bundle.cfg.opt = OPT_SROUTES | OPT_IDCHECK | OPT_LOOPBACK | 774 OPT_THROUGHPUT | OPT_UTMP; 775 *bundle.cfg.label = '\0'; 776 bundle.cfg.mtu = DEF_MTU; 777 bundle.cfg.autoload.max.packets = 0; 778 bundle.cfg.autoload.max.timeout = 0; 779 bundle.cfg.autoload.min.packets = 0; 780 bundle.cfg.autoload.min.timeout = 0; 781 bundle.phys_type = type; 782 783 bundle.links = datalink_Create("deflink", &bundle, type); 784 if (bundle.links == NULL) { 785 log_Printf(LogERROR, "Cannot create data link: %s\n", strerror(errno)); 786 close(bundle.dev.fd); 787 bundle.ifp.Name = NULL; 788 return NULL; 789 } 790 791 bundle.desc.type = BUNDLE_DESCRIPTOR; 792 bundle.desc.next = NULL; 793 bundle.desc.UpdateSet = bundle_UpdateSet; 794 bundle.desc.IsSet = bundle_IsSet; 795 bundle.desc.Read = bundle_DescriptorRead; 796 bundle.desc.Write = bundle_DescriptorWrite; 797 798 mp_Init(&bundle.ncp.mp, &bundle); 799 800 /* Send over the first physical link by default */ 801 ipcp_Init(&bundle.ncp.ipcp, &bundle, &bundle.links->physical->link, 802 &bundle.fsm); 803 804 memset(&bundle.filter, '\0', sizeof bundle.filter); 805 bundle.filter.in.fragok = bundle.filter.in.logok = 1; 806 bundle.filter.in.name = "IN"; 807 bundle.filter.out.fragok = bundle.filter.out.logok = 1; 808 bundle.filter.out.name = "OUT"; 809 bundle.filter.dial.name = "DIAL"; 810 bundle.filter.dial.logok = 1; 811 bundle.filter.alive.name = "ALIVE"; 812 bundle.filter.alive.logok = 1; 813 memset(&bundle.idle.timer, '\0', sizeof bundle.idle.timer); 814 bundle.idle.done = 0; 815 bundle.notify.fd = -1; 816 memset(&bundle.autoload.timer, '\0', sizeof bundle.autoload.timer); 817 bundle.autoload.done = 0; 818 bundle.autoload.running = 0; 819 820 /* Clean out any leftover crud */ 821 bundle_CleanInterface(&bundle); 822 823 if (prompt) { 824 /* Retrospectively introduce ourselves to the prompt */ 825 prompt->bundle = &bundle; 826 bundle_RegisterDescriptor(&bundle, &prompt->desc); 827 } 828 829 return &bundle; 830} 831 832static void 833bundle_DownInterface(struct bundle *bundle) 834{ 835 struct ifreq ifrq; 836 int s; 837 838 route_IfDelete(bundle, 1); 839 840 s = ID0socket(AF_INET, SOCK_DGRAM, 0); 841 if (s < 0) { 842 log_Printf(LogERROR, "bundle_DownInterface: socket: %s\n", strerror(errno)); 843 return; 844 } 845 846 memset(&ifrq, '\0', sizeof ifrq); 847 strncpy(ifrq.ifr_name, bundle->ifp.Name, sizeof ifrq.ifr_name - 1); 848 ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; 849 if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { 850 log_Printf(LogERROR, "bundle_DownInterface: ioctl(SIOCGIFFLAGS): %s\n", 851 strerror(errno)); 852 close(s); 853 return; 854 } 855 ifrq.ifr_flags &= ~IFF_UP; 856 if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { 857 log_Printf(LogERROR, "bundle_DownInterface: ioctl(SIOCSIFFLAGS): %s\n", 858 strerror(errno)); 859 close(s); 860 return; 861 } 862 close(s); 863} 864 865void 866bundle_Destroy(struct bundle *bundle) 867{ 868 struct datalink *dl; 869 struct descriptor *desc, *ndesc; 870 871 /* 872 * Clean up the interface. We don't need to timer_Stop()s, mp_Down(), 873 * ipcp_CleanInterface() and bundle_DownInterface() unless we're getting 874 * out under exceptional conditions such as a descriptor exception. 875 */ 876 timer_Stop(&bundle->idle.timer); 877 timer_Stop(&bundle->autoload.timer); 878 mp_Down(&bundle->ncp.mp); 879 ipcp_CleanInterface(&bundle->ncp.ipcp); 880 bundle_DownInterface(bundle); 881 882 /* Again, these are all DATALINK_CLOSED unless we're abending */ 883 dl = bundle->links; 884 while (dl) 885 dl = datalink_Destroy(dl); 886 887 /* In case we never made PHASE_NETWORK */ 888 bundle_Notify(bundle, EX_ERRDEAD); 889 890 /* Finally, destroy our prompts */ 891 desc = bundle->desc.next; 892 while (desc) { 893 ndesc = desc->next; 894 if (desc->type == PROMPT_DESCRIPTOR) 895 prompt_Destroy((struct prompt *)desc, 1); 896 else 897 log_Printf(LogERROR, "bundle_Destroy: Don't know how to delete descriptor" 898 " type %d\n", desc->type); 899 desc = ndesc; 900 } 901 bundle->desc.next = NULL; 902 bundle->ifp.Name = NULL; 903} 904 905struct rtmsg { 906 struct rt_msghdr m_rtm; 907 char m_space[64]; 908}; 909 910int 911bundle_SetRoute(struct bundle *bundle, int cmd, struct in_addr dst, 912 struct in_addr gateway, struct in_addr mask, int bang) 913{ 914 struct rtmsg rtmes; 915 int s, nb, wb; 916 char *cp; 917 const char *cmdstr; 918 struct sockaddr_in rtdata; 919 int result = 1; 920 921 if (bang) 922 cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!"); 923 else 924 cmdstr = (cmd == RTM_ADD ? "Add" : "Delete"); 925 s = ID0socket(PF_ROUTE, SOCK_RAW, 0); 926 if (s < 0) { 927 log_Printf(LogERROR, "bundle_SetRoute: socket(): %s\n", strerror(errno)); 928 return result; 929 } 930 memset(&rtmes, '\0', sizeof rtmes); 931 rtmes.m_rtm.rtm_version = RTM_VERSION; 932 rtmes.m_rtm.rtm_type = cmd; 933 rtmes.m_rtm.rtm_addrs = RTA_DST; 934 rtmes.m_rtm.rtm_seq = ++bundle->routing_seq; 935 rtmes.m_rtm.rtm_pid = getpid(); 936 rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 937 938 memset(&rtdata, '\0', sizeof rtdata); 939 rtdata.sin_len = sizeof rtdata; 940 rtdata.sin_family = AF_INET; 941 rtdata.sin_port = 0; 942 rtdata.sin_addr = dst; 943 944 cp = rtmes.m_space; 945 memcpy(cp, &rtdata, rtdata.sin_len); 946 cp += rtdata.sin_len; 947 if (cmd == RTM_ADD) { 948 if (gateway.s_addr == INADDR_ANY) { 949 /* Add a route through the interface */ 950 struct sockaddr_dl dl; 951 const char *iname; 952 int ilen; 953 954 iname = Index2Nam(bundle->ifp.Index); 955 ilen = strlen(iname); 956 dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen; 957 dl.sdl_family = AF_LINK; 958 dl.sdl_index = bundle->ifp.Index; 959 dl.sdl_type = 0; 960 dl.sdl_nlen = ilen; 961 dl.sdl_alen = 0; 962 dl.sdl_slen = 0; 963 strncpy(dl.sdl_data, iname, sizeof dl.sdl_data); 964 memcpy(cp, &dl, dl.sdl_len); 965 cp += dl.sdl_len; 966 rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 967 } else { 968 rtdata.sin_addr = gateway; 969 memcpy(cp, &rtdata, rtdata.sin_len); 970 cp += rtdata.sin_len; 971 rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 972 } 973 } 974 975 if (dst.s_addr == INADDR_ANY) 976 mask.s_addr = INADDR_ANY; 977 978 if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) { 979 rtdata.sin_addr = mask; 980 memcpy(cp, &rtdata, rtdata.sin_len); 981 cp += rtdata.sin_len; 982 rtmes.m_rtm.rtm_addrs |= RTA_NETMASK; 983 } 984 985 nb = cp - (char *) &rtmes; 986 rtmes.m_rtm.rtm_msglen = nb; 987 wb = ID0write(s, &rtmes, nb); 988 if (wb < 0) { 989 log_Printf(LogTCPIP, "bundle_SetRoute failure:\n"); 990 log_Printf(LogTCPIP, "bundle_SetRoute: Cmd = %s\n", cmdstr); 991 log_Printf(LogTCPIP, "bundle_SetRoute: Dst = %s\n", inet_ntoa(dst)); 992 log_Printf(LogTCPIP, "bundle_SetRoute: Gateway = %s\n", inet_ntoa(gateway)); 993 log_Printf(LogTCPIP, "bundle_SetRoute: Mask = %s\n", inet_ntoa(mask)); 994failed: 995 if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST || 996 (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) { 997 if (!bang) { 998 log_Printf(LogWARN, "Add route failed: %s already exists\n", 999 inet_ntoa(dst)); 1000 result = 0; /* Don't add to our dynamic list */ 1001 } else { 1002 rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE; 1003 if ((wb = ID0write(s, &rtmes, nb)) < 0) 1004 goto failed; 1005 } 1006 } else if (cmd == RTM_DELETE && 1007 (rtmes.m_rtm.rtm_errno == ESRCH || 1008 (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) { 1009 if (!bang) 1010 log_Printf(LogWARN, "Del route failed: %s: Non-existent\n", 1011 inet_ntoa(dst)); 1012 } else if (rtmes.m_rtm.rtm_errno == 0) 1013 log_Printf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr, 1014 inet_ntoa(dst), strerror(errno)); 1015 else 1016 log_Printf(LogWARN, "%s route failed: %s: %s\n", 1017 cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno)); 1018 } 1019 log_Printf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n", 1020 wb, cmdstr, (unsigned)dst.s_addr, (unsigned)gateway.s_addr); 1021 close(s); 1022 1023 return result; 1024} 1025 1026void 1027bundle_LinkClosed(struct bundle *bundle, struct datalink *dl) 1028{ 1029 /* 1030 * Our datalink has closed. 1031 * CleanDatalinks() (called from DoLoop()) will remove closed 1032 * 1OFF and DIRECT links. 1033 * If it's the last data link, enter phase DEAD. 1034 * 1035 * NOTE: dl may not be in our list (bundle_SendDatalink()) ! 1036 */ 1037 1038 struct datalink *odl; 1039 int other_links; 1040 1041 other_links = 0; 1042 for (odl = bundle->links; odl; odl = odl->next) 1043 if (odl != dl && odl->state != DATALINK_CLOSED) 1044 other_links++; 1045 1046 if (!other_links) { 1047 if (dl->physical->type != PHYS_DEMAND) /* Not in -auto mode */ 1048 bundle_DownInterface(bundle); 1049 if (bundle->ncp.ipcp.fsm.state > ST_CLOSED || 1050 bundle->ncp.ipcp.fsm.state == ST_STARTING) { 1051 fsm_Down(&bundle->ncp.ipcp.fsm); 1052 fsm_Close(&bundle->ncp.ipcp.fsm); /* ST_INITIAL please */ 1053 } 1054 bundle_NewPhase(bundle, PHASE_DEAD); 1055 bundle_DisplayPrompt(bundle); 1056 bundle_StopAutoLoadTimer(bundle); 1057 bundle->autoload.running = 0; 1058 } else 1059 bundle->autoload.running = 1; 1060} 1061 1062void 1063bundle_Open(struct bundle *bundle, const char *name, int mask) 1064{ 1065 /* 1066 * Please open the given datalink, or all if name == NULL 1067 */ 1068 struct datalink *dl; 1069 1070 timer_Stop(&bundle->autoload.timer); 1071 for (dl = bundle->links; dl; dl = dl->next) 1072 if (name == NULL || !strcasecmp(dl->name, name)) { 1073 if (dl->state == DATALINK_CLOSED && (mask & dl->physical->type)) { 1074 datalink_Up(dl, 1, 1); 1075 if (mask == PHYS_DEMAND) 1076 /* Only one DEMAND link at a time (see the AutoLoad timer) */ 1077 break; 1078 } 1079 if (name != NULL) 1080 break; 1081 } 1082} 1083 1084struct datalink * 1085bundle2datalink(struct bundle *bundle, const char *name) 1086{ 1087 struct datalink *dl; 1088 1089 if (name != NULL) { 1090 for (dl = bundle->links; dl; dl = dl->next) 1091 if (!strcasecmp(dl->name, name)) 1092 return dl; 1093 } else if (bundle->links && !bundle->links->next) 1094 return bundle->links; 1095 1096 return NULL; 1097} 1098 1099int 1100bundle_FillQueues(struct bundle *bundle) 1101{ 1102 int total; 1103 1104 if (bundle->ncp.mp.active) 1105 total = mp_FillQueues(bundle); 1106 else { 1107 struct datalink *dl; 1108 int add; 1109 1110 for (total = 0, dl = bundle->links; dl; dl = dl->next) 1111 if (dl->state == DATALINK_OPEN) { 1112 add = link_QueueLen(&dl->physical->link); 1113 if (add == 0 && dl->physical->out == NULL) 1114 add = ip_FlushPacket(&dl->physical->link, bundle); 1115 total += add; 1116 } 1117 } 1118 1119 return total + ip_QueueLen(); 1120} 1121 1122int 1123bundle_ShowLinks(struct cmdargs const *arg) 1124{ 1125 struct datalink *dl; 1126 1127 for (dl = arg->bundle->links; dl; dl = dl->next) { 1128 prompt_Printf(arg->prompt, "Name: %s [%s]", dl->name, datalink_State(dl)); 1129 if (dl->physical->link.throughput.rolling && dl->state == DATALINK_OPEN) 1130 prompt_Printf(arg->prompt, " (weight %d, %d bytes/sec)", 1131 dl->mp.weight, 1132 dl->physical->link.throughput.OctetsPerSecond); 1133 prompt_Printf(arg->prompt, "\n"); 1134 } 1135 1136 return 0; 1137} 1138 1139static const char * 1140optval(struct bundle *bundle, int bit) 1141{ 1142 return (bundle->cfg.opt & bit) ? "enabled" : "disabled"; 1143} 1144 1145int 1146bundle_ShowStatus(struct cmdargs const *arg) 1147{ 1148 int remaining; 1149 1150 prompt_Printf(arg->prompt, "Phase %s\n", bundle_PhaseName(arg->bundle)); 1151 prompt_Printf(arg->prompt, " Device: %s\n", arg->bundle->dev.Name); 1152 prompt_Printf(arg->prompt, " Interface: %s @ %lubps\n", 1153 arg->bundle->ifp.Name, arg->bundle->ifp.Speed); 1154 1155 prompt_Printf(arg->prompt, "\nDefaults:\n"); 1156 prompt_Printf(arg->prompt, " Label: %s\n", arg->bundle->cfg.label); 1157 prompt_Printf(arg->prompt, " Auth name: %s\n", 1158 arg->bundle->cfg.auth.name); 1159 prompt_Printf(arg->prompt, " Auto Load: Up after %ds of >= %d packets\n", 1160 arg->bundle->cfg.autoload.max.timeout, 1161 arg->bundle->cfg.autoload.max.packets); 1162 prompt_Printf(arg->prompt, " Down after %ds of <= %d" 1163 " packets\n", arg->bundle->cfg.autoload.min.timeout, 1164 arg->bundle->cfg.autoload.min.packets); 1165 if (arg->bundle->autoload.timer.state == TIMER_RUNNING) 1166 prompt_Printf(arg->prompt, " %ds remaining 'till " 1167 "a link comes %s\n", 1168 bundle_RemainingAutoLoadTime(arg->bundle), 1169 arg->bundle->autoload.comingup ? "up" : "down"); 1170 else 1171 prompt_Printf(arg->prompt, " %srunning with %d" 1172 " packets queued\n", arg->bundle->autoload.running ? 1173 "" : "not ", ip_QueueLen()); 1174 1175 prompt_Printf(arg->prompt, " Idle Timer: "); 1176 if (arg->bundle->cfg.idle_timeout) { 1177 prompt_Printf(arg->prompt, "%ds", arg->bundle->cfg.idle_timeout); 1178 remaining = bundle_RemainingIdleTime(arg->bundle); 1179 if (remaining != -1) 1180 prompt_Printf(arg->prompt, " (%ds remaining)", remaining); 1181 prompt_Printf(arg->prompt, "\n"); 1182 } else 1183 prompt_Printf(arg->prompt, "disabled\n"); 1184 prompt_Printf(arg->prompt, " MTU: "); 1185 if (arg->bundle->cfg.mtu) 1186 prompt_Printf(arg->prompt, "%d\n", arg->bundle->cfg.mtu); 1187 else 1188 prompt_Printf(arg->prompt, "unspecified\n"); 1189 1190 prompt_Printf(arg->prompt, " Sticky Routes: %s\n", 1191 optval(arg->bundle, OPT_SROUTES)); 1192 prompt_Printf(arg->prompt, " ID check: %s\n", 1193 optval(arg->bundle, OPT_IDCHECK)); 1194 prompt_Printf(arg->prompt, " Loopback: %s\n", 1195 optval(arg->bundle, OPT_LOOPBACK)); 1196 prompt_Printf(arg->prompt, " PasswdAuth: %s\n", 1197 optval(arg->bundle, OPT_PASSWDAUTH)); 1198 prompt_Printf(arg->prompt, " Proxy: %s\n", 1199 optval(arg->bundle, OPT_PROXY)); 1200 prompt_Printf(arg->prompt, " Throughput: %s\n", 1201 optval(arg->bundle, OPT_THROUGHPUT)); 1202 prompt_Printf(arg->prompt, " Utmp Logging: %s\n", 1203 optval(arg->bundle, OPT_UTMP)); 1204 1205 return 0; 1206} 1207 1208static void 1209bundle_IdleTimeout(void *v) 1210{ 1211 struct bundle *bundle = (struct bundle *)v; 1212 1213 log_Printf(LogPHASE, "Idle timer expired.\n"); 1214 bundle_StopIdleTimer(bundle); 1215 bundle_Close(bundle, NULL, 1); 1216} 1217 1218/* 1219 * Start Idle timer. If timeout is reached, we call bundle_Close() to 1220 * close LCP and link. 1221 */ 1222void 1223bundle_StartIdleTimer(struct bundle *bundle) 1224{ 1225 timer_Stop(&bundle->idle.timer); 1226 if ((bundle->phys_type & (PHYS_DEDICATED|PHYS_PERM)) != bundle->phys_type && 1227 bundle->cfg.idle_timeout) { 1228 bundle->idle.timer.func = bundle_IdleTimeout; 1229 bundle->idle.timer.name = "idle"; 1230 bundle->idle.timer.load = bundle->cfg.idle_timeout * SECTICKS; 1231 bundle->idle.timer.arg = bundle; 1232 timer_Start(&bundle->idle.timer); 1233 bundle->idle.done = time(NULL) + bundle->cfg.idle_timeout; 1234 } 1235} 1236 1237void 1238bundle_SetIdleTimer(struct bundle *bundle, int value) 1239{ 1240 bundle->cfg.idle_timeout = value; 1241 if (bundle_LinkIsUp(bundle)) 1242 bundle_StartIdleTimer(bundle); 1243} 1244 1245void 1246bundle_StopIdleTimer(struct bundle *bundle) 1247{ 1248 timer_Stop(&bundle->idle.timer); 1249 bundle->idle.done = 0; 1250} 1251 1252static int 1253bundle_RemainingIdleTime(struct bundle *bundle) 1254{ 1255 if (bundle->idle.done) 1256 return bundle->idle.done - time(NULL); 1257 return -1; 1258} 1259 1260int 1261bundle_IsDead(struct bundle *bundle) 1262{ 1263 return !bundle->links || (bundle->phase == PHASE_DEAD && bundle->CleaningUp); 1264} 1265 1266void 1267bundle_RegisterDescriptor(struct bundle *bundle, struct descriptor *d) 1268{ 1269 d->next = bundle->desc.next; 1270 bundle->desc.next = d; 1271} 1272 1273void 1274bundle_UnRegisterDescriptor(struct bundle *bundle, struct descriptor *d) 1275{ 1276 struct descriptor **desc; 1277 1278 for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next) 1279 if (*desc == d) { 1280 *desc = d->next; 1281 break; 1282 } 1283} 1284 1285void 1286bundle_DelPromptDescriptors(struct bundle *bundle, struct server *s) 1287{ 1288 struct descriptor **desc; 1289 struct prompt *p; 1290 1291 desc = &bundle->desc.next; 1292 while (*desc) { 1293 if ((*desc)->type == PROMPT_DESCRIPTOR) { 1294 p = (struct prompt *)*desc; 1295 if (p->owner == s) { 1296 prompt_Destroy(p, 1); 1297 desc = &bundle->desc.next; 1298 continue; 1299 } 1300 } 1301 desc = &(*desc)->next; 1302 } 1303} 1304 1305void 1306bundle_DisplayPrompt(struct bundle *bundle) 1307{ 1308 struct descriptor **desc; 1309 1310 for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next) 1311 if ((*desc)->type == PROMPT_DESCRIPTOR) 1312 prompt_Required((struct prompt *)*desc); 1313} 1314 1315void 1316bundle_WriteTermPrompt(struct bundle *bundle, struct datalink *dl, 1317 const char *data, int len) 1318{ 1319 struct descriptor *desc; 1320 struct prompt *p; 1321 1322 for (desc = bundle->desc.next; desc; desc = desc->next) 1323 if (desc->type == PROMPT_DESCRIPTOR) { 1324 p = (struct prompt *)desc; 1325 if (prompt_IsTermMode(p, dl)) 1326 prompt_Printf(p, "%.*s", len, data); 1327 } 1328} 1329 1330void 1331bundle_SetTtyCommandMode(struct bundle *bundle, struct datalink *dl) 1332{ 1333 struct descriptor *desc; 1334 struct prompt *p; 1335 1336 for (desc = bundle->desc.next; desc; desc = desc->next) 1337 if (desc->type == PROMPT_DESCRIPTOR) { 1338 p = (struct prompt *)desc; 1339 if (prompt_IsTermMode(p, dl)) 1340 prompt_TtyCommandMode(p); 1341 } 1342} 1343 1344static void 1345bundle_LinkAdded(struct bundle *bundle, struct datalink *dl) 1346{ 1347 bundle->phys_type |= dl->physical->type; 1348 if (dl->physical->type == PHYS_DEMAND && 1349 bundle->autoload.timer.state == TIMER_STOPPED && 1350 bundle->phase == PHASE_NETWORK) 1351 bundle->autoload.running = 1; 1352} 1353 1354static void 1355bundle_LinksRemoved(struct bundle *bundle) 1356{ 1357 struct datalink *dl; 1358 1359 bundle->phys_type = 0; 1360 for (dl = bundle->links; dl; dl = dl->next) 1361 bundle_LinkAdded(bundle, dl); 1362 1363 if ((bundle->phys_type & (PHYS_DEDICATED|PHYS_PERM)) == bundle->phys_type) 1364 timer_Stop(&bundle->idle.timer); 1365} 1366 1367static struct datalink * 1368bundle_DatalinkLinkout(struct bundle *bundle, struct datalink *dl) 1369{ 1370 struct datalink **dlp; 1371 1372 if (dl->state == DATALINK_CLOSED) 1373 for (dlp = &bundle->links; *dlp; dlp = &(*dlp)->next) 1374 if (*dlp == dl) { 1375 *dlp = dl->next; 1376 dl->next = NULL; 1377 bundle_LinksRemoved(bundle); 1378 return dl; 1379 } 1380 1381 return NULL; 1382} 1383 1384static void 1385bundle_DatalinkLinkin(struct bundle *bundle, struct datalink *dl) 1386{ 1387 struct datalink **dlp = &bundle->links; 1388 1389 while (*dlp) 1390 dlp = &(*dlp)->next; 1391 1392 *dlp = dl; 1393 dl->next = NULL; 1394 1395 bundle_LinkAdded(bundle, dl); 1396} 1397 1398void 1399bundle_CleanDatalinks(struct bundle *bundle) 1400{ 1401 struct datalink **dlp = &bundle->links; 1402 int found = 0; 1403 1404 while (*dlp) 1405 if ((*dlp)->state == DATALINK_CLOSED && 1406 (*dlp)->physical->type & (PHYS_DIRECT|PHYS_1OFF)) { 1407 *dlp = datalink_Destroy(*dlp); 1408 found++; 1409 } else 1410 dlp = &(*dlp)->next; 1411 1412 if (found) 1413 bundle_LinksRemoved(bundle); 1414} 1415 1416int 1417bundle_DatalinkClone(struct bundle *bundle, struct datalink *dl, 1418 const char *name) 1419{ 1420 if (bundle2datalink(bundle, name)) { 1421 log_Printf(LogWARN, "Clone: %s: name already exists\n", name); 1422 return 0; 1423 } 1424 1425 bundle_DatalinkLinkin(bundle, datalink_Clone(dl, name)); 1426 return 1; 1427} 1428 1429void 1430bundle_DatalinkRemove(struct bundle *bundle, struct datalink *dl) 1431{ 1432 dl = bundle_DatalinkLinkout(bundle, dl); 1433 if (dl) 1434 datalink_Destroy(dl); 1435} 1436 1437void 1438bundle_SetLabel(struct bundle *bundle, const char *label) 1439{ 1440 if (label) 1441 strncpy(bundle->cfg.label, label, sizeof bundle->cfg.label - 1); 1442 else 1443 *bundle->cfg.label = '\0'; 1444} 1445 1446const char * 1447bundle_GetLabel(struct bundle *bundle) 1448{ 1449 return *bundle->cfg.label ? bundle->cfg.label : NULL; 1450} 1451 1452void 1453bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun) 1454{ 1455 char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)]; 1456 struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf; 1457 struct msghdr msg; 1458 struct iovec iov[SCATTER_SEGMENTS]; 1459 struct datalink *dl; 1460 int niov, link_fd, expect, f; 1461 1462 log_Printf(LogPHASE, "Receiving datalink\n"); 1463 1464 /* Create our scatter/gather array */ 1465 niov = 1; 1466 iov[0].iov_len = strlen(Version) + 1; 1467 iov[0].iov_base = (char *)malloc(iov[0].iov_len); 1468 if (datalink2iov(NULL, iov, &niov, sizeof iov / sizeof *iov) == -1) 1469 return; 1470 1471 for (f = expect = 0; f < niov; f++) 1472 expect += iov[f].iov_len; 1473 1474 /* Set up our message */ 1475 cmsg->cmsg_len = sizeof cmsgbuf; 1476 cmsg->cmsg_level = SOL_SOCKET; 1477 cmsg->cmsg_type = SCM_RIGHTS; 1478 1479 memset(&msg, '\0', sizeof msg); 1480 msg.msg_name = (caddr_t)sun; 1481 msg.msg_namelen = sizeof *sun; 1482 msg.msg_iov = iov; 1483 msg.msg_iovlen = niov; 1484 msg.msg_control = cmsgbuf; 1485 msg.msg_controllen = sizeof cmsgbuf; 1486 1487 log_Printf(LogDEBUG, "Expecting %d scatter/gather bytes\n", expect); 1488 f = expect + 100; 1489 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &f, sizeof f); 1490 if ((f = recvmsg(s, &msg, MSG_WAITALL)) != expect) { 1491 if (f == -1) 1492 log_Printf(LogERROR, "Failed recvmsg: %s\n", strerror(errno)); 1493 else 1494 log_Printf(LogERROR, "Failed recvmsg: Got %d, not %d\n", f, expect); 1495 while (niov--) 1496 free(iov[niov].iov_base); 1497 return; 1498 } 1499 1500 /* We've successfully received an open file descriptor through our socket */ 1501 link_fd = *(int *)CMSG_DATA(cmsg); 1502 1503 write(s, "!",1 ); /* ACK */ 1504 1505 if (strncmp(Version, iov[0].iov_base, iov[0].iov_len)) { 1506 log_Printf(LogWARN, "Cannot receive datalink, incorrect version" 1507 " (\"%.*s\", not \"%s\")\n", (int)iov[0].iov_len, 1508 iov[0].iov_base, Version); 1509 close(link_fd); 1510 while (niov--) 1511 free(iov[niov].iov_base); 1512 return; 1513 } 1514 1515 niov = 1; 1516 dl = iov2datalink(bundle, iov, &niov, sizeof iov / sizeof *iov, link_fd); 1517 if (dl) { 1518 bundle_DatalinkLinkin(bundle, dl); 1519 datalink_AuthOk(dl); 1520 } else 1521 close(link_fd); 1522 1523 free(iov[0].iov_base); 1524} 1525 1526void 1527bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) 1528{ 1529 char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)], ack; 1530 struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf; 1531 struct msghdr msg; 1532 struct iovec iov[SCATTER_SEGMENTS]; 1533 int niov, link_fd, f, expect; 1534 1535 log_Printf(LogPHASE, "Transmitting datalink %s\n", dl->name); 1536 1537 bundle_DatalinkLinkout(dl->bundle, dl); 1538 bundle_LinkClosed(dl->bundle, dl); 1539 1540 /* Build our scatter/gather array */ 1541 iov[0].iov_len = strlen(Version) + 1; 1542 iov[0].iov_base = strdup(Version); 1543 niov = 1; 1544 1545 link_fd = datalink2iov(dl, iov, &niov, sizeof iov / sizeof *iov); 1546 1547 if (link_fd != -1) { 1548 cmsg->cmsg_len = sizeof cmsgbuf; 1549 cmsg->cmsg_level = SOL_SOCKET; 1550 cmsg->cmsg_type = SCM_RIGHTS; 1551 *(int *)CMSG_DATA(cmsg) = link_fd; 1552 1553 memset(&msg, '\0', sizeof msg); 1554 msg.msg_name = (caddr_t)sun; 1555 msg.msg_namelen = sizeof *sun; 1556 msg.msg_iov = iov; 1557 msg.msg_iovlen = niov; 1558 msg.msg_control = cmsgbuf; 1559 msg.msg_controllen = sizeof cmsgbuf; 1560 1561 for (f = expect = 0; f < niov; f++) 1562 expect += iov[f].iov_len; 1563 1564 log_Printf(LogDEBUG, "Sending %d bytes in scatter/gather array\n", expect); 1565 1566 f = expect + SOCKET_OVERHEAD; 1567 setsockopt(s, SOL_SOCKET, SO_SNDBUF, &f, sizeof f); 1568 if (sendmsg(s, &msg, 0) == -1) 1569 log_Printf(LogERROR, "Failed sendmsg: %s\n", strerror(errno)); 1570 /* We must get the ACK before closing the descriptor ! */ 1571 read(s, &ack, 1); 1572 close(link_fd); 1573 } 1574 1575 while (niov--) 1576 free(iov[niov].iov_base); 1577} 1578 1579int 1580bundle_RenameDatalink(struct bundle *bundle, struct datalink *ndl, 1581 const char *name) 1582{ 1583 struct datalink *dl; 1584 1585 if (!strcasecmp(ndl->name, name)) 1586 return 1; 1587 1588 for (dl = bundle->links; dl; dl = dl->next) 1589 if (!strcasecmp(dl->name, name)) 1590 return 0; 1591 1592 datalink_Rename(ndl, name); 1593 return 1; 1594} 1595 1596int 1597bundle_SetMode(struct bundle *bundle, struct datalink *dl, int mode) 1598{ 1599 int omode; 1600 1601 omode = dl->physical->type; 1602 if (omode == mode) 1603 return 1; 1604 1605 if (mode == PHYS_DEMAND && !(bundle->phys_type & PHYS_DEMAND)) 1606 /* Changing to demand-dial mode */ 1607 if (bundle->ncp.ipcp.peer_ip.s_addr == INADDR_ANY) { 1608 log_Printf(LogWARN, "You must `set ifaddr' before changing mode to %s\n", 1609 mode2Nam(mode)); 1610 return 0; 1611 } 1612 1613 if (!datalink_SetMode(dl, mode)) 1614 return 0; 1615 1616 if (mode == PHYS_DEMAND && !(bundle->phys_type & PHYS_DEMAND)) 1617 ipcp_InterfaceUp(&bundle->ncp.ipcp); 1618 1619 /* Regenerate phys_type and adjust autoload & idle timers */ 1620 bundle_LinksRemoved(bundle); 1621 1622 if (omode == PHYS_DEMAND && !(bundle->phys_type & PHYS_DEMAND)) 1623 /* Changing from demand-dial mode */ 1624 ipcp_CleanInterface(&bundle->ncp.ipcp); 1625 1626 return 1; 1627} 1628