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.1.2.43 1998/04/07 23:45:41 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 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <sys/ioctl.h> 44 #include <termios.h> 45 #include <unistd.h> 46 47 #include "command.h" 48 #include "mbuf.h" 49 #include "log.h" 50 #include "id.h" 51 #include "defs.h" 52 #include "timer.h" 53 #include "fsm.h" 54 #include "iplist.h" 55 #include "lqr.h" 56 #include "hdlc.h" 57 #include "throughput.h" 58 #include "slcompress.h" 59 #include "ipcp.h" 60 #include "filter.h" 61 #include "descriptor.h" 62 #include "route.h" 63 #include "lcp.h" 64 #include "ccp.h" 65 #include "link.h" 66 #include "mp.h" 67 #include "bundle.h" 68 #include "async.h" 69 #include "physical.h" 70 #include "modem.h" 71 #include "auth.h" 72 #include "lcpproto.h" 73 #include "chap.h" 74 #include "tun.h" 75 #include "prompt.h" 76 #include "chat.h" 77 #include "datalink.h" 78 #include "ip.h" 79 80 static const char *PhaseNames[] = { 81 "Dead", "Establish", "Authenticate", "Network", "Terminate" 82 }; 83 84 const char * 85 bundle_PhaseName(struct bundle *bundle) 86 { 87 return bundle->phase <= PHASE_TERMINATE ? 88 PhaseNames[bundle->phase] : "unknown"; 89 } 90 91 void 92 bundle_NewPhase(struct bundle *bundle, u_int new) 93 { 94 if (new == bundle->phase) 95 return; 96 97 if (new <= PHASE_TERMINATE) 98 LogPrintf(LogPHASE, "bundle: %s\n", PhaseNames[new]); 99 100 switch (new) { 101 case PHASE_DEAD: 102 bundle->phase = new; 103 break; 104 105 case PHASE_ESTABLISH: 106 bundle->phase = new; 107 break; 108 109 case PHASE_AUTHENTICATE: 110 bundle->phase = new; 111 bundle_DisplayPrompt(bundle); 112 break; 113 114 case PHASE_NETWORK: 115 ipcp_Setup(&bundle->ncp.ipcp); 116 FsmUp(&bundle->ncp.ipcp.fsm); 117 FsmOpen(&bundle->ncp.ipcp.fsm); 118 /* Fall through */ 119 120 case PHASE_TERMINATE: 121 bundle->phase = new; 122 bundle_DisplayPrompt(bundle); 123 break; 124 } 125 } 126 127 static int 128 bundle_CleanInterface(const struct bundle *bundle) 129 { 130 int s; 131 struct ifreq ifrq; 132 struct ifaliasreq ifra; 133 134 s = ID0socket(AF_INET, SOCK_DGRAM, 0); 135 if (s < 0) { 136 LogPrintf(LogERROR, "bundle_CleanInterface: socket(): %s\n", 137 strerror(errno)); 138 return (-1); 139 } 140 strncpy(ifrq.ifr_name, bundle->ifname, sizeof ifrq.ifr_name - 1); 141 ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; 142 while (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0) { 143 memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask); 144 strncpy(ifra.ifra_name, bundle->ifname, sizeof ifra.ifra_name - 1); 145 ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 146 ifra.ifra_addr = ifrq.ifr_addr; 147 if (ID0ioctl(s, SIOCGIFDSTADDR, &ifrq) < 0) { 148 if (ifra.ifra_addr.sa_family == AF_INET) 149 LogPrintf(LogERROR, 150 "bundle_CleanInterface: Can't get dst for %s on %s !\n", 151 inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr), 152 bundle->ifname); 153 return 0; 154 } 155 ifra.ifra_broadaddr = ifrq.ifr_dstaddr; 156 if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) { 157 if (ifra.ifra_addr.sa_family == AF_INET) 158 LogPrintf(LogERROR, 159 "bundle_CleanInterface: Can't delete %s address on %s !\n", 160 inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr), 161 bundle->ifname); 162 return 0; 163 } 164 } 165 166 return 1; 167 } 168 169 static void 170 bundle_LayerStart(void *v, struct fsm *fp) 171 { 172 /* The given FSM is about to start up ! */ 173 } 174 175 176 static void 177 bundle_Notify(struct bundle *bundle, char c) 178 { 179 if (bundle->notify.fd != -1) { 180 if (write(bundle->notify.fd, &c, 1) == 1) 181 LogPrintf(LogPHASE, "Parent notified of success.\n"); 182 else 183 LogPrintf(LogPHASE, "Failed to notify parent of success.\n"); 184 close(bundle->notify.fd); 185 bundle->notify.fd = -1; 186 } 187 } 188 189 static void 190 bundle_vLayerUp(void *v, struct fsm *fp) 191 { 192 bundle_LayerUp((struct bundle *)v, fp); 193 } 194 195 void 196 bundle_LayerUp(struct bundle *bundle, struct fsm *fp) 197 { 198 /* 199 * The given fsm is now up 200 * If it's an LCP (including MP initialisation), set our mtu 201 * (This routine is also called from mp_Init() with it's LCP) 202 * If it's an NCP, tell our -background parent to go away. 203 * If it's the first NCP, start the idle timer. 204 */ 205 206 if (fp->proto == PROTO_LCP) { 207 if (bundle->ncp.mp.active) { 208 int speed; 209 struct datalink *dl; 210 211 for (dl = bundle->links, speed = 0; dl; dl = dl->next) 212 speed += modem_Speed(dl->physical); 213 if (speed) 214 tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru, speed); 215 } else 216 tun_configure(bundle, fsm2lcp(fp)->his_mru, 217 modem_Speed(link2physical(fp->link))); 218 } else if (fp->proto == PROTO_IPCP) { 219 bundle_StartIdleTimer(bundle); 220 bundle_Notify(bundle, EX_NORMAL); 221 } 222 } 223 224 static void 225 bundle_LayerDown(void *v, struct fsm *fp) 226 { 227 /* 228 * The given FSM has been told to come down. 229 * If it's our last NCP, stop the idle timer. 230 * If it's our last NCP *OR* LCP, enter TERMINATE phase. 231 * If it's an LCP and we're in multilink mode, adjust our tun speed. 232 */ 233 234 struct bundle *bundle = (struct bundle *)v; 235 236 if (fp->proto == PROTO_IPCP) { 237 bundle_StopIdleTimer(bundle); 238 bundle_NewPhase(bundle, PHASE_TERMINATE); 239 } else if (fp->proto == PROTO_LCP) { 240 int speed, others_active; 241 struct datalink *dl; 242 243 others_active = 0; 244 for (dl = bundle->links, speed = 0; dl; dl = dl->next) 245 if (fp != &dl->physical->link.lcp.fsm && 246 dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) { 247 speed += modem_Speed(dl->physical); 248 others_active++; 249 } 250 if (bundle->ncp.mp.active && speed) 251 tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru, speed); 252 253 if (!others_active) 254 bundle_NewPhase(bundle, PHASE_TERMINATE); 255 } 256 } 257 258 static void 259 bundle_LayerFinish(void *v, struct fsm *fp) 260 { 261 /* The given fsm is now down (fp cannot be NULL) 262 * 263 * If it's the last LCP, FsmDown all NCPs 264 * If it's the last NCP, FsmClose all LCPs 265 */ 266 267 struct bundle *bundle = (struct bundle *)v; 268 struct datalink *dl; 269 270 if (fp->proto == PROTO_IPCP) { 271 for (dl = bundle->links; dl; dl = dl->next) 272 datalink_Close(dl, 0); 273 FsmDown(fp); 274 FsmClose(fp); 275 } else if (fp->proto == PROTO_LCP) { 276 int others_active; 277 278 others_active = 0; 279 for (dl = bundle->links; dl; dl = dl->next) 280 if (fp != &dl->physical->link.lcp.fsm && 281 dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) 282 others_active++; 283 284 if (!others_active) { 285 FsmDown(&bundle->ncp.ipcp.fsm); 286 FsmClose(&bundle->ncp.ipcp.fsm); /* ST_INITIAL please */ 287 } 288 } 289 } 290 291 int 292 bundle_LinkIsUp(const struct bundle *bundle) 293 { 294 return bundle->ncp.ipcp.fsm.state == ST_OPENED; 295 } 296 297 void 298 bundle_Close(struct bundle *bundle, const char *name, int staydown) 299 { 300 /* 301 * Please close the given datalink. 302 * If name == NULL or name is the last datalink, enter TERMINATE phase 303 * and FsmClose all NCPs (except our MP) 304 * If it isn't the last datalink, just Close that datalink. 305 */ 306 307 struct datalink *dl, *this_dl; 308 int others_active; 309 310 if (bundle->phase == PHASE_TERMINATE || bundle->phase == PHASE_DEAD) 311 return; 312 313 others_active = 0; 314 this_dl = NULL; 315 316 for (dl = bundle->links; dl; dl = dl->next) { 317 if (name && !strcasecmp(name, dl->name)) 318 this_dl = dl; 319 if (name == NULL || this_dl == dl) { 320 if (staydown) 321 datalink_StayDown(dl); 322 } else if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) 323 others_active++; 324 } 325 326 if (name && this_dl == NULL) { 327 LogPrintf(LogWARN, "%s: Invalid datalink name\n", name); 328 return; 329 } 330 331 if (!others_active) { 332 if (bundle->ncp.ipcp.fsm.state > ST_CLOSED || 333 bundle->ncp.ipcp.fsm.state == ST_STARTING) 334 FsmClose(&bundle->ncp.ipcp.fsm); 335 else { 336 if (bundle->ncp.ipcp.fsm.state > ST_INITIAL) { 337 FsmClose(&bundle->ncp.ipcp.fsm); 338 FsmDown(&bundle->ncp.ipcp.fsm); 339 } 340 for (dl = bundle->links; dl; dl = dl->next) 341 datalink_Close(dl, staydown); 342 } 343 } else if (this_dl && this_dl->state != DATALINK_CLOSED && 344 this_dl->state != DATALINK_HANGUP) 345 datalink_Close(this_dl, staydown); 346 } 347 348 static int 349 bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 350 { 351 struct bundle *bundle = descriptor2bundle(d); 352 struct datalink *dl; 353 struct descriptor *desc; 354 int result; 355 356 result = 0; 357 for (dl = bundle->links; dl; dl = dl->next) 358 result += descriptor_UpdateSet(&dl->desc, r, w, e, n); 359 360 for (desc = bundle->desc.next; desc; desc = desc->next) 361 result += descriptor_UpdateSet(desc, r, w, e, n); 362 363 return result; 364 } 365 366 static int 367 bundle_IsSet(struct descriptor *d, const fd_set *fdset) 368 { 369 struct bundle *bundle = descriptor2bundle(d); 370 struct datalink *dl; 371 struct descriptor *desc; 372 373 for (dl = bundle->links; dl; dl = dl->next) 374 if (descriptor_IsSet(&dl->desc, fdset)) 375 return 1; 376 377 for (desc = bundle->desc.next; desc; desc = desc->next) 378 if (descriptor_IsSet(desc, fdset)) 379 return 1; 380 381 return 0; 382 } 383 384 static void 385 bundle_DescriptorRead(struct descriptor *d, struct bundle *bundle, 386 const fd_set *fdset) 387 { 388 struct datalink *dl; 389 struct descriptor *desc; 390 391 for (dl = bundle->links; dl; dl = dl->next) 392 if (descriptor_IsSet(&dl->desc, fdset)) 393 descriptor_Read(&dl->desc, bundle, fdset); 394 395 for (desc = bundle->desc.next; desc; desc = desc->next) 396 if (descriptor_IsSet(desc, fdset)) 397 descriptor_Read(desc, bundle, fdset); 398 } 399 400 static void 401 bundle_DescriptorWrite(struct descriptor *d, struct bundle *bundle, 402 const fd_set *fdset) 403 { 404 struct datalink *dl; 405 struct descriptor *desc; 406 407 for (dl = bundle->links; dl; dl = dl->next) 408 if (descriptor_IsSet(&dl->desc, fdset)) 409 descriptor_Write(&dl->desc, bundle, fdset); 410 411 for (desc = bundle->desc.next; desc; desc = desc->next) 412 if (descriptor_IsSet(desc, fdset)) 413 descriptor_Write(desc, bundle, fdset); 414 } 415 416 417 #define MAX_TUN 256 418 /* 419 * MAX_TUN is set at 256 because that is the largest minor number 420 * we can use (certainly with mknod(1) anyway). The search for a 421 * device aborts when it reaches the first `Device not configured' 422 * (ENXIO) or the third `No such file or directory' (ENOENT) error. 423 */ 424 struct bundle * 425 bundle_Create(const char *prefix, struct prompt *prompt, int type) 426 { 427 int s, enoentcount, err; 428 struct ifreq ifrq; 429 static struct bundle bundle; /* there can be only one */ 430 431 if (bundle.ifname != NULL) { /* Already allocated ! */ 432 LogPrintf(LogERROR, "bundle_Create: There's only one BUNDLE !\n"); 433 return NULL; 434 } 435 436 err = ENOENT; 437 enoentcount = 0; 438 for (bundle.unit = 0; bundle.unit <= MAX_TUN; bundle.unit++) { 439 snprintf(bundle.dev, sizeof bundle.dev, "%s%d", prefix, bundle.unit); 440 bundle.tun_fd = ID0open(bundle.dev, O_RDWR); 441 if (bundle.tun_fd >= 0) 442 break; 443 if (errno == ENXIO) { 444 bundle.unit = MAX_TUN; 445 err = errno; 446 } else if (errno == ENOENT) { 447 if (++enoentcount > 2) 448 bundle.unit = MAX_TUN; 449 } else 450 err = errno; 451 } 452 453 if (bundle.unit > MAX_TUN) { 454 prompt_Printf(prompt, "No tunnel device is available (%s).\n", 455 strerror(err)); 456 return NULL; 457 } 458 459 LogSetTun(bundle.unit); 460 461 s = socket(AF_INET, SOCK_DGRAM, 0); 462 if (s < 0) { 463 LogPrintf(LogERROR, "bundle_Create: socket(): %s\n", strerror(errno)); 464 close(bundle.tun_fd); 465 return NULL; 466 } 467 468 bundle.ifname = strrchr(bundle.dev, '/'); 469 if (bundle.ifname == NULL) 470 bundle.ifname = bundle.dev; 471 else 472 bundle.ifname++; 473 474 /* 475 * Now, bring up the interface. 476 */ 477 memset(&ifrq, '\0', sizeof ifrq); 478 strncpy(ifrq.ifr_name, bundle.ifname, sizeof ifrq.ifr_name - 1); 479 ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; 480 if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { 481 LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCGIFFLAGS): %s\n", 482 strerror(errno)); 483 close(s); 484 close(bundle.tun_fd); 485 bundle.ifname = NULL; 486 return NULL; 487 } 488 ifrq.ifr_flags |= IFF_UP; 489 if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { 490 LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCSIFFLAGS): %s\n", 491 strerror(errno)); 492 close(s); 493 close(bundle.tun_fd); 494 bundle.ifname = NULL; 495 return NULL; 496 } 497 498 close(s); 499 500 if ((bundle.ifIndex = GetIfIndex(bundle.ifname)) < 0) { 501 LogPrintf(LogERROR, "OpenTunnel: Can't find ifindex.\n"); 502 close(bundle.tun_fd); 503 bundle.ifname = NULL; 504 return NULL; 505 } 506 507 prompt_Printf(prompt, "Using interface: %s\n", bundle.ifname); 508 LogPrintf(LogPHASE, "Using interface: %s\n", bundle.ifname); 509 510 bundle.routing_seq = 0; 511 bundle.phase = PHASE_DEAD; 512 bundle.CleaningUp = 0; 513 514 bundle.fsm.LayerStart = bundle_LayerStart; 515 bundle.fsm.LayerUp = bundle_vLayerUp; 516 bundle.fsm.LayerDown = bundle_LayerDown; 517 bundle.fsm.LayerFinish = bundle_LayerFinish; 518 bundle.fsm.object = &bundle; 519 520 bundle.cfg.idle_timeout = NCP_IDLE_TIMEOUT; 521 bundle.phys_type = type; 522 523 bundle.links = datalink_Create("default", &bundle, &bundle.fsm, type); 524 if (bundle.links == NULL) { 525 LogPrintf(LogERROR, "Cannot create data link: %s\n", strerror(errno)); 526 close(bundle.tun_fd); 527 bundle.ifname = NULL; 528 return NULL; 529 } 530 531 bundle.desc.type = BUNDLE_DESCRIPTOR; 532 bundle.desc.next = NULL; 533 bundle.desc.UpdateSet = bundle_UpdateSet; 534 bundle.desc.IsSet = bundle_IsSet; 535 bundle.desc.Read = bundle_DescriptorRead; 536 bundle.desc.Write = bundle_DescriptorWrite; 537 538 ipcp_Init(&bundle.ncp.ipcp, &bundle, &bundle.links->physical->link, 539 &bundle.fsm); 540 541 memset(&bundle.filter, '\0', sizeof bundle.filter); 542 bundle.filter.in.fragok = bundle.filter.in.logok = 1; 543 bundle.filter.in.name = "IN"; 544 bundle.filter.out.fragok = bundle.filter.out.logok = 1; 545 bundle.filter.out.name = "OUT"; 546 bundle.filter.dial.name = "DIAL"; 547 bundle.filter.dial.logok = 1; 548 bundle.filter.alive.name = "ALIVE"; 549 bundle.filter.alive.logok = 1; 550 memset(&bundle.idle.timer, '\0', sizeof bundle.idle.timer); 551 bundle.idle.done = 0; 552 bundle.notify.fd = -1; 553 554 /* Clean out any leftover crud */ 555 bundle_CleanInterface(&bundle); 556 557 if (prompt) { 558 /* Retrospectively introduce ourselves to the prompt */ 559 prompt->bundle = &bundle; 560 bundle_RegisterDescriptor(&bundle, &prompt->desc); 561 } 562 563 return &bundle; 564 } 565 566 static void 567 bundle_DownInterface(struct bundle *bundle) 568 { 569 struct ifreq ifrq; 570 int s; 571 572 DeleteIfRoutes(bundle, 1); 573 574 s = ID0socket(AF_INET, SOCK_DGRAM, 0); 575 if (s < 0) { 576 LogPrintf(LogERROR, "bundle_DownInterface: socket: %s\n", strerror(errno)); 577 return; 578 } 579 580 memset(&ifrq, '\0', sizeof ifrq); 581 strncpy(ifrq.ifr_name, bundle->ifname, sizeof ifrq.ifr_name - 1); 582 ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; 583 if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { 584 LogPrintf(LogERROR, "bundle_DownInterface: ioctl(SIOCGIFFLAGS): %s\n", 585 strerror(errno)); 586 close(s); 587 return; 588 } 589 ifrq.ifr_flags &= ~IFF_UP; 590 if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { 591 LogPrintf(LogERROR, "bundle_DownInterface: ioctl(SIOCSIFFLAGS): %s\n", 592 strerror(errno)); 593 close(s); 594 return; 595 } 596 close(s); 597 } 598 599 void 600 bundle_Destroy(struct bundle *bundle) 601 { 602 struct datalink *dl; 603 struct descriptor *desc, *ndesc; 604 605 if (bundle->phys_type & PHYS_DEMAND) { 606 IpcpCleanInterface(&bundle->ncp.ipcp); 607 bundle_DownInterface(bundle); 608 } 609 610 dl = bundle->links; 611 while (dl) 612 dl = datalink_Destroy(dl); 613 614 bundle_Notify(bundle, EX_ERRDEAD); 615 616 desc = bundle->desc.next; 617 while (desc) { 618 ndesc = desc->next; 619 if (desc->type == PROMPT_DESCRIPTOR) 620 prompt_Destroy((struct prompt *)desc, 1); 621 else 622 LogPrintf(LogERROR, "bundle_Destroy: Don't know how to delete descriptor" 623 " type %d\n", desc->type); 624 desc = ndesc; 625 } 626 bundle->desc.next = NULL; 627 bundle->ifname = NULL; 628 } 629 630 struct rtmsg { 631 struct rt_msghdr m_rtm; 632 char m_space[64]; 633 }; 634 635 void 636 bundle_SetRoute(struct bundle *bundle, int cmd, struct in_addr dst, 637 struct in_addr gateway, struct in_addr mask, int bang) 638 { 639 struct rtmsg rtmes; 640 int s, nb, wb; 641 char *cp; 642 const char *cmdstr; 643 struct sockaddr_in rtdata; 644 645 if (bang) 646 cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!"); 647 else 648 cmdstr = (cmd == RTM_ADD ? "Add" : "Delete"); 649 s = ID0socket(PF_ROUTE, SOCK_RAW, 0); 650 if (s < 0) { 651 LogPrintf(LogERROR, "bundle_SetRoute: socket(): %s\n", strerror(errno)); 652 return; 653 } 654 memset(&rtmes, '\0', sizeof rtmes); 655 rtmes.m_rtm.rtm_version = RTM_VERSION; 656 rtmes.m_rtm.rtm_type = cmd; 657 rtmes.m_rtm.rtm_addrs = RTA_DST; 658 rtmes.m_rtm.rtm_seq = ++bundle->routing_seq; 659 rtmes.m_rtm.rtm_pid = getpid(); 660 rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 661 662 memset(&rtdata, '\0', sizeof rtdata); 663 rtdata.sin_len = 16; 664 rtdata.sin_family = AF_INET; 665 rtdata.sin_port = 0; 666 rtdata.sin_addr = dst; 667 668 cp = rtmes.m_space; 669 memcpy(cp, &rtdata, 16); 670 cp += 16; 671 if (cmd == RTM_ADD) 672 if (gateway.s_addr == INADDR_ANY) { 673 /* Add a route through the interface */ 674 struct sockaddr_dl dl; 675 const char *iname; 676 int ilen; 677 678 iname = Index2Nam(bundle->ifIndex); 679 ilen = strlen(iname); 680 dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen; 681 dl.sdl_family = AF_LINK; 682 dl.sdl_index = bundle->ifIndex; 683 dl.sdl_type = 0; 684 dl.sdl_nlen = ilen; 685 dl.sdl_alen = 0; 686 dl.sdl_slen = 0; 687 strncpy(dl.sdl_data, iname, sizeof dl.sdl_data); 688 memcpy(cp, &dl, dl.sdl_len); 689 cp += dl.sdl_len; 690 rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 691 } else { 692 rtdata.sin_addr = gateway; 693 memcpy(cp, &rtdata, 16); 694 cp += 16; 695 rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 696 } 697 698 if (dst.s_addr == INADDR_ANY) 699 mask.s_addr = INADDR_ANY; 700 701 if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) { 702 rtdata.sin_addr = mask; 703 memcpy(cp, &rtdata, 16); 704 cp += 16; 705 rtmes.m_rtm.rtm_addrs |= RTA_NETMASK; 706 } 707 708 nb = cp - (char *) &rtmes; 709 rtmes.m_rtm.rtm_msglen = nb; 710 wb = ID0write(s, &rtmes, nb); 711 if (wb < 0) { 712 LogPrintf(LogTCPIP, "bundle_SetRoute failure:\n"); 713 LogPrintf(LogTCPIP, "bundle_SetRoute: Cmd = %s\n", cmd); 714 LogPrintf(LogTCPIP, "bundle_SetRoute: Dst = %s\n", inet_ntoa(dst)); 715 LogPrintf(LogTCPIP, "bundle_SetRoute: Gateway = %s\n", inet_ntoa(gateway)); 716 LogPrintf(LogTCPIP, "bundle_SetRoute: Mask = %s\n", inet_ntoa(mask)); 717 failed: 718 if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST || 719 (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) 720 if (!bang) 721 LogPrintf(LogWARN, "Add route failed: %s already exists\n", 722 inet_ntoa(dst)); 723 else { 724 rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE; 725 if ((wb = ID0write(s, &rtmes, nb)) < 0) 726 goto failed; 727 } 728 else if (cmd == RTM_DELETE && 729 (rtmes.m_rtm.rtm_errno == ESRCH || 730 (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) { 731 if (!bang) 732 LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n", 733 inet_ntoa(dst)); 734 } else if (rtmes.m_rtm.rtm_errno == 0) 735 LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr, 736 inet_ntoa(dst), strerror(errno)); 737 else 738 LogPrintf(LogWARN, "%s route failed: %s: %s\n", 739 cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno)); 740 } 741 LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n", 742 wb, cmdstr, dst.s_addr, gateway.s_addr); 743 close(s); 744 } 745 746 void 747 bundle_LinkLost(struct bundle *bundle, struct physical *p, int staydown) 748 { 749 /* 750 * Locate the appropriate datalink, and Down it. 751 * 752 * The LayerFinish() called from the datalinks LCP will 753 * potentially Down our NCPs (if it's the last link). 754 * 755 * The LinkClosed() called when the datalink is finally in 756 * the CLOSED state MAY cause the entire datalink to be deleted 757 * and MAY cause a program exit. 758 */ 759 760 if (p->type == PHYS_STDIN || bundle->CleaningUp) 761 staydown = 1; 762 datalink_Down(p->dl, staydown); 763 } 764 765 void 766 bundle_LinkClosed(struct bundle *bundle, struct datalink *dl) 767 { 768 /* 769 * Our datalink has closed. 770 * UpdateSet() will remove 1OFF and STDIN links. 771 * If it's the last data link, enter phase DEAD. 772 */ 773 774 struct datalink *odl; 775 int other_links; 776 777 other_links = 0; 778 for (odl = bundle->links; odl; odl = odl->next) 779 if (odl != dl && odl->state != DATALINK_CLOSED) 780 other_links++; 781 782 if (!other_links) { 783 if (dl->physical->type != PHYS_DEMAND) 784 bundle_DownInterface(bundle); 785 bundle_NewPhase(bundle, PHASE_DEAD); 786 bundle_DisplayPrompt(bundle); 787 } 788 } 789 790 void 791 bundle_Open(struct bundle *bundle, const char *name, int mask) 792 { 793 /* 794 * Please open the given datalink, or all if name == NULL 795 */ 796 struct datalink *dl; 797 798 for (dl = bundle->links; dl; dl = dl->next) 799 if (name == NULL || !strcasecmp(dl->name, name)) { 800 if (mask & dl->physical->type) 801 datalink_Up(dl, 1, 1); 802 if (name != NULL) 803 break; 804 } 805 } 806 807 struct datalink * 808 bundle2datalink(struct bundle *bundle, const char *name) 809 { 810 struct datalink *dl; 811 812 if (name != NULL) { 813 for (dl = bundle->links; dl; dl = dl->next) 814 if (!strcasecmp(dl->name, name)) 815 return dl; 816 } else if (bundle->links && !bundle->links->next) 817 return bundle->links; 818 819 return NULL; 820 } 821 822 int 823 bundle_FillQueues(struct bundle *bundle) 824 { 825 int total; 826 827 if (bundle->ncp.mp.active) { 828 total = mp_FillQueues(bundle); 829 } else { 830 total = link_QueueLen(&bundle->links->physical->link); 831 if (total == 0 && bundle->links->physical->out == NULL) 832 total = IpFlushPacket(&bundle->links->physical->link, bundle); 833 } 834 835 return total + ip_QueueLen(); 836 } 837 838 int 839 bundle_ShowLinks(struct cmdargs const *arg) 840 { 841 if (arg->cx) 842 datalink_Show(arg->cx, arg->prompt); 843 else { 844 struct datalink *dl; 845 846 for (dl = arg->bundle->links; dl; dl = dl->next) 847 datalink_Show(dl, arg->prompt); 848 } 849 850 return 0; 851 } 852 853 static void 854 bundle_IdleTimeout(void *v) 855 { 856 struct bundle *bundle = (struct bundle *)v; 857 858 bundle->idle.done = 0; 859 LogPrintf(LogPHASE, "IPCP Idle timer expired.\n"); 860 bundle_Close(bundle, NULL, 1); 861 } 862 863 /* 864 * Start Idle timer. If timeout is reached, we call bundle_Close() to 865 * close LCP and link. 866 */ 867 void 868 bundle_StartIdleTimer(struct bundle *bundle) 869 { 870 if (!(bundle->phys_type & (PHYS_DEDICATED|PHYS_PERM)) && 871 bundle->cfg.idle_timeout) { 872 StopTimer(&bundle->idle.timer); 873 bundle->idle.timer.func = bundle_IdleTimeout; 874 bundle->idle.timer.name = "idle"; 875 bundle->idle.timer.load = bundle->cfg.idle_timeout * SECTICKS; 876 bundle->idle.timer.state = TIMER_STOPPED; 877 bundle->idle.timer.arg = bundle; 878 StartTimer(&bundle->idle.timer); 879 bundle->idle.done = time(NULL) + bundle->cfg.idle_timeout; 880 } 881 } 882 883 void 884 bundle_SetIdleTimer(struct bundle *bundle, int value) 885 { 886 bundle->cfg.idle_timeout = value; 887 if (bundle_LinkIsUp(bundle)) 888 bundle_StartIdleTimer(bundle); 889 } 890 891 void 892 bundle_StopIdleTimer(struct bundle *bundle) 893 { 894 StopTimer(&bundle->idle.timer); 895 bundle->idle.done = 0; 896 } 897 898 int 899 bundle_RemainingIdleTime(struct bundle *bundle) 900 { 901 if (bundle->idle.done) 902 return bundle->idle.done - time(NULL); 903 return -1; 904 } 905 906 int 907 bundle_IsDead(struct bundle *bundle) 908 { 909 return !bundle->links || (bundle->phase == PHASE_DEAD && bundle->CleaningUp); 910 } 911 912 void 913 bundle_RegisterDescriptor(struct bundle *bundle, struct descriptor *d) 914 { 915 d->next = bundle->desc.next; 916 bundle->desc.next = d; 917 } 918 919 void 920 bundle_UnRegisterDescriptor(struct bundle *bundle, struct descriptor *d) 921 { 922 struct descriptor **desc; 923 924 for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next) 925 if (*desc == d) { 926 *desc = d->next; 927 break; 928 } 929 } 930 931 void 932 bundle_DelPromptDescriptors(struct bundle *bundle, struct server *s) 933 { 934 struct descriptor **desc; 935 struct prompt *p; 936 937 desc = &bundle->desc.next; 938 while (*desc) { 939 if ((*desc)->type == PROMPT_DESCRIPTOR) { 940 p = (struct prompt *)*desc; 941 if (p->owner == s) { 942 prompt_Destroy(p, 1); 943 desc = &bundle->desc.next; 944 continue; 945 } 946 } 947 desc = &(*desc)->next; 948 } 949 } 950 951 void 952 bundle_DisplayPrompt(struct bundle *bundle) 953 { 954 struct descriptor **desc; 955 956 for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next) 957 if ((*desc)->type == PROMPT_DESCRIPTOR) 958 prompt_Required((struct prompt *)*desc); 959 } 960 961 void 962 bundle_WriteTermPrompt(struct bundle *bundle, struct datalink *dl, 963 const char *data, int len) 964 { 965 struct descriptor *desc; 966 struct prompt *p; 967 968 for (desc = bundle->desc.next; desc; desc = desc->next) 969 if (desc->type == PROMPT_DESCRIPTOR) { 970 p = (struct prompt *)desc; 971 if (prompt_IsTermMode(p, dl)) 972 prompt_Printf(p, "%.*s", len, data); 973 } 974 } 975 976 void 977 bundle_SetTtyCommandMode(struct bundle *bundle, struct datalink *dl) 978 { 979 struct descriptor *desc; 980 struct prompt *p; 981 982 for (desc = bundle->desc.next; desc; desc = desc->next) 983 if (desc->type == PROMPT_DESCRIPTOR) { 984 p = (struct prompt *)desc; 985 if (prompt_IsTermMode(p, dl)) 986 prompt_TtyCommandMode(p); 987 } 988 } 989 990 static void 991 bundle_GenPhysType(struct bundle *bundle) 992 { 993 struct datalink *dl; 994 995 bundle->phys_type = 0; 996 for (dl = bundle->links; dl; dl = dl->next) 997 bundle->phys_type |= dl->physical->type; 998 } 999 1000 void 1001 bundle_DatalinkClone(struct bundle *bundle, struct datalink *dl, 1002 const char *name) 1003 { 1004 struct datalink *ndl = datalink_Clone(dl, name); 1005 1006 ndl->next = dl->next; 1007 dl->next = ndl; 1008 bundle_GenPhysType(bundle); 1009 } 1010 1011 void 1012 bundle_DatalinkRemove(struct bundle *bundle, struct datalink *dl) 1013 { 1014 struct datalink **dlp; 1015 1016 if (dl->state == DATALINK_CLOSED) 1017 for (dlp = &bundle->links; *dlp; dlp = &(*dlp)->next) 1018 if (*dlp == dl) { 1019 *dlp = datalink_Destroy(dl); 1020 break; 1021 } 1022 bundle_GenPhysType(bundle); 1023 } 1024 1025 void 1026 bundle_CleanDatalinks(struct bundle *bundle) 1027 { 1028 struct datalink **dlp = &bundle->links; 1029 1030 while (*dlp) 1031 if ((*dlp)->state == DATALINK_CLOSED && 1032 (*dlp)->physical->type & (PHYS_STDIN|PHYS_1OFF)) 1033 *dlp = datalink_Destroy(*dlp); 1034 else 1035 dlp = &(*dlp)->next; 1036 bundle_GenPhysType(bundle); 1037 } 1038