1 /*- 2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 4 * Internet Initiative Japan, Inc (IIJ) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <netinet/in.h> 33 #include <netinet/in_systm.h> 34 #include <netinet/ip.h> 35 #include <sys/un.h> 36 #include <sys/socket.h> 37 #include <net/route.h> 38 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <paths.h> 42 #include <signal.h> 43 #include <stdarg.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <sys/time.h> 48 #include <termios.h> 49 #include <unistd.h> 50 #include <sys/stat.h> 51 52 #ifndef NONAT 53 #ifdef LOCALNAT 54 #include "alias.h" 55 #else 56 #include <alias.h> 57 #endif 58 #endif 59 60 #include "layer.h" 61 #include "probe.h" 62 #include "mbuf.h" 63 #include "log.h" 64 #include "defs.h" 65 #include "id.h" 66 #include "timer.h" 67 #include "fsm.h" 68 #include "lqr.h" 69 #include "hdlc.h" 70 #include "lcp.h" 71 #include "ccp.h" 72 #include "iplist.h" 73 #include "throughput.h" 74 #include "slcompress.h" 75 #include "ncpaddr.h" 76 #include "ipcp.h" 77 #include "filter.h" 78 #include "descriptor.h" 79 #include "link.h" 80 #include "mp.h" 81 #ifndef NORADIUS 82 #include "radius.h" 83 #endif 84 #include "ipv6cp.h" 85 #include "ncp.h" 86 #include "bundle.h" 87 #include "auth.h" 88 #include "systems.h" 89 #include "sig.h" 90 #include "main.h" 91 #include "server.h" 92 #include "prompt.h" 93 #include "chat.h" 94 #include "chap.h" 95 #include "cbcp.h" 96 #include "datalink.h" 97 #include "iface.h" 98 99 #ifndef O_NONBLOCK 100 #ifdef O_NDELAY 101 #define O_NONBLOCK O_NDELAY 102 #endif 103 #endif 104 105 static void DoLoop(struct bundle *); 106 static void TerminalStop(int); 107 108 static struct bundle *SignalBundle; 109 static struct prompt *SignalPrompt; 110 111 void 112 Cleanup(int excode) 113 { 114 SignalBundle->CleaningUp = 1; 115 bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 116 } 117 118 void 119 AbortProgram(int excode) 120 { 121 if (SignalBundle) 122 server_Close(SignalBundle); 123 log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 124 if (SignalBundle) { 125 bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 126 bundle_Destroy(SignalBundle); 127 } 128 log_Close(); 129 exit(excode); 130 } 131 132 static void 133 CloseConnection(int signo) 134 { 135 /* NOTE, these are manual, we've done a setsid() */ 136 sig_signal(SIGINT, SIG_IGN); 137 log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 138 bundle_Down(SignalBundle, CLOSE_STAYDOWN); 139 sig_signal(SIGINT, CloseConnection); 140 } 141 142 static void 143 CloseSession(int signo) 144 { 145 log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 146 Cleanup(EX_TERM); 147 } 148 149 static pid_t BGPid = 0; 150 151 static void 152 KillChild(int signo) 153 { 154 signal(signo, SIG_IGN); 155 log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 156 kill(BGPid, SIGINT); 157 } 158 159 static void 160 TerminalCont(int signo) 161 { 162 signal(SIGCONT, SIG_DFL); 163 prompt_Continue(SignalPrompt); 164 } 165 166 static void 167 TerminalStop(int signo) 168 { 169 prompt_Suspend(SignalPrompt); 170 signal(SIGCONT, TerminalCont); 171 raise(SIGSTOP); 172 } 173 174 static void 175 BringDownServer(int signo) 176 { 177 /* Drops all child prompts too ! */ 178 if (server_Close(SignalBundle)) 179 log_Printf(LogPHASE, "Closed server socket\n"); 180 } 181 182 static void 183 RestartServer(int signo) 184 { 185 /* Drops all child prompts and re-opens the socket */ 186 server_Reopen(SignalBundle); 187 } 188 189 static void 190 Usage(void) 191 { 192 fprintf(stderr, "usage: ppp [-auto | -foreground | -background | -direct |" 193 " -dedicated | -ddial | -interactive]" 194 #ifndef NOALIAS 195 " [-nat]" 196 #endif 197 " [-quiet] [-unit N] [system ...]\n"); 198 exit(EX_START); 199 } 200 201 struct switches { 202 unsigned nat : 1; 203 unsigned fg : 1; 204 unsigned quiet : 1; 205 int mode; 206 int unit; 207 }; 208 209 static int 210 ProcessArgs(int argc, char **argv, struct switches *sw) 211 { 212 int optc, newmode, arg; 213 char *cp; 214 215 optc = 0; 216 memset(sw, '\0', sizeof *sw); 217 sw->mode = PHYS_INTERACTIVE; 218 sw->unit = -1; 219 220 for (arg = 1; arg < argc && *argv[arg] == '-'; arg++, optc++) { 221 cp = argv[arg] + 1; 222 newmode = Nam2mode(cp); 223 switch (newmode) { 224 case PHYS_NONE: 225 if (strcmp(cp, "nat") == 0) { 226 #ifdef NONAT 227 log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 228 #else 229 sw->nat = 1; 230 #endif 231 optc--; /* this option isn't exclusive */ 232 } else if (strcmp(cp, "alias") == 0) { 233 #ifdef NONAT 234 log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 235 fprintf(stderr, "%s ignored: NAT is compiled out\n", argv[arg]); 236 #else 237 log_Printf(LogWARN, "%s is deprecated\n", argv[arg]); 238 fprintf(stderr, "%s is deprecated\n", argv[arg]); 239 sw->nat = 1; 240 #endif 241 optc--; /* this option isn't exclusive */ 242 } else if (strncmp(cp, "unit", 4) == 0) { 243 optc--; /* this option isn't exclusive */ 244 if (cp[4] == '\0') { 245 optc--; /* nor is the argument */ 246 if (++arg == argc) { 247 fprintf(stderr, "-unit: Expected unit number\n"); 248 Usage(); 249 } else 250 sw->unit = atoi(argv[arg]); 251 } else 252 sw->unit = atoi(cp + 4); 253 } else if (strcmp(cp, "quiet") == 0) { 254 sw->quiet = 1; 255 optc--; /* this option isn't exclusive */ 256 } else 257 Usage(); 258 break; 259 260 case PHYS_ALL: 261 Usage(); 262 break; 263 264 default: 265 sw->mode = newmode; 266 if (newmode == PHYS_FOREGROUND) 267 sw->fg = 1; 268 } 269 } 270 271 if (optc > 1) { 272 fprintf(stderr, "You may specify only one mode.\n"); 273 exit(EX_START); 274 } 275 276 if (sw->mode == PHYS_AUTO && arg == argc) { 277 fprintf(stderr, "A system must be specified in auto mode.\n"); 278 exit(EX_START); 279 } 280 281 return arg; /* Don't SetLabel yet ! */ 282 } 283 284 static void 285 CheckLabel(const char *label, struct prompt *prompt, int mode) 286 { 287 const char *err; 288 289 if ((err = system_IsValid(label, prompt, mode)) != NULL) { 290 fprintf(stderr, "%s: %s\n", label, err); 291 if (mode == PHYS_DIRECT) 292 log_Printf(LogWARN, "Label %s rejected -direct connection: %s\n", 293 label, err); 294 log_Close(); 295 exit(1); 296 } 297 } 298 299 300 int 301 main(int argc, char **argv) 302 { 303 char *name; 304 const char *lastlabel; 305 int arg, f, holdfd[3], label; 306 struct bundle *bundle; 307 struct prompt *prompt; 308 struct switches sw; 309 310 probe_Init(); 311 312 /* 313 * We open 3 descriptors to ensure that STDIN_FILENO, STDOUT_FILENO and 314 * STDERR_FILENO are always open. These are closed before DoLoop(), 315 * but *after* we've avoided the possibility of erroneously closing 316 * an important descriptor with close(STD{IN,OUT,ERR}_FILENO). 317 */ 318 if ((holdfd[0] = open(_PATH_DEVNULL, O_RDWR)) == -1) { 319 fprintf(stderr, "Cannot open %s !\n", _PATH_DEVNULL); 320 return 2; 321 } 322 for (f = 1; f < sizeof holdfd / sizeof *holdfd; f++) 323 holdfd[f] = dup(holdfd[0]); 324 325 name = strrchr(argv[0], '/'); 326 log_Open(name ? name + 1 : argv[0]); 327 328 #ifndef NONAT 329 PacketAliasInit(); 330 #endif 331 label = ProcessArgs(argc, argv, &sw); 332 333 /* 334 * A FreeBSD & OpenBSD hack to dodge a bug in the tty driver that drops 335 * output occasionally.... I must find the real reason some time. To 336 * display the dodgy behaviour, comment out this bit, make yourself a large 337 * routing table and then run ppp in interactive mode. The `show route' 338 * command will drop chunks of data !!! 339 */ 340 if (sw.mode == PHYS_INTERACTIVE) { 341 close(STDIN_FILENO); 342 if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 343 fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 344 return 2; 345 } 346 } 347 348 /* Allow output for the moment (except in direct mode) */ 349 if (sw.mode == PHYS_DIRECT) 350 prompt = NULL; 351 else 352 SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 353 354 ID0init(); 355 if (ID0realuid() != 0) { 356 char conf[200], *ptr; 357 358 snprintf(conf, sizeof conf, "%s/%s", PPP_CONFDIR, CONFFILE); 359 do { 360 struct stat sb; 361 362 if (stat(conf, &sb) == 0 && sb.st_mode & S_IWOTH) { 363 log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 364 conf); 365 return -1; 366 } 367 ptr = conf + strlen(conf)-2; 368 while (ptr > conf && *ptr != '/') 369 *ptr-- = '\0'; 370 } while (ptr >= conf); 371 } 372 373 if (label < argc) 374 for (arg = label; arg < argc; arg++) 375 CheckLabel(argv[arg], prompt, sw.mode); 376 else 377 CheckLabel("default", prompt, sw.mode); 378 379 if (!sw.quiet) 380 prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(sw.mode)); 381 382 if ((bundle = bundle_Create(TUN_PREFIX, sw.mode, sw.unit)) == NULL) 383 return EX_START; 384 385 /* NOTE: We may now have changed argv[1] via a ``set proctitle'' */ 386 387 if (prompt) { 388 prompt->bundle = bundle; /* couldn't do it earlier */ 389 if (!sw.quiet) 390 prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 391 } 392 SignalBundle = bundle; 393 bundle->NatEnabled = sw.nat; 394 if (sw.nat) 395 bundle->cfg.opt |= OPT_IFACEALIAS; 396 397 if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 398 prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 399 400 sig_signal(SIGHUP, CloseSession); 401 sig_signal(SIGTERM, CloseSession); 402 sig_signal(SIGINT, CloseConnection); 403 sig_signal(SIGQUIT, CloseSession); 404 sig_signal(SIGALRM, SIG_IGN); 405 signal(SIGPIPE, SIG_IGN); 406 407 if (sw.mode == PHYS_INTERACTIVE) 408 sig_signal(SIGTSTP, TerminalStop); 409 410 sig_signal(SIGUSR1, RestartServer); 411 sig_signal(SIGUSR2, BringDownServer); 412 413 lastlabel = argv[argc - 1]; 414 for (arg = label; arg < argc; arg++) { 415 /* In case we use LABEL or ``set enddisc label'' */ 416 bundle_SetLabel(bundle, lastlabel); 417 system_Select(bundle, argv[arg], CONFFILE, prompt, NULL); 418 } 419 420 if (label < argc) 421 /* In case the last label did a ``load'' */ 422 bundle_SetLabel(bundle, lastlabel); 423 424 if (sw.mode == PHYS_AUTO && 425 ncprange_family(&bundle->ncp.ipcp.cfg.peer_range) == AF_UNSPEC) { 426 prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address " 427 "in auto mode.\n"); 428 AbortProgram(EX_START); 429 } 430 431 if (sw.mode != PHYS_INTERACTIVE) { 432 if (sw.mode != PHYS_DIRECT) { 433 if (!sw.fg) { 434 int bgpipe[2]; 435 pid_t bgpid; 436 437 if (sw.mode == PHYS_BACKGROUND && pipe(bgpipe)) { 438 log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 439 AbortProgram(EX_SOCK); 440 } 441 442 bgpid = fork(); 443 if (bgpid == -1) { 444 log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 445 AbortProgram(EX_SOCK); 446 } 447 448 if (bgpid) { 449 char c = EX_NORMAL; 450 int ret; 451 452 if (sw.mode == PHYS_BACKGROUND) { 453 close(bgpipe[1]); 454 BGPid = bgpid; 455 /* If we get a signal, kill the child */ 456 signal(SIGHUP, KillChild); 457 signal(SIGTERM, KillChild); 458 signal(SIGINT, KillChild); 459 signal(SIGQUIT, KillChild); 460 461 /* Wait for our child to close its pipe before we exit */ 462 while ((ret = read(bgpipe[0], &c, 1)) == 1) { 463 switch (c) { 464 case EX_NORMAL: 465 if (!sw.quiet) { 466 prompt_Printf(prompt, "PPP enabled\n"); 467 log_Printf(LogPHASE, "Parent: PPP enabled\n"); 468 } 469 break; 470 case EX_REDIAL: 471 if (!sw.quiet) 472 prompt_Printf(prompt, "Attempting redial\n"); 473 continue; 474 case EX_RECONNECT: 475 if (!sw.quiet) 476 prompt_Printf(prompt, "Attempting reconnect\n"); 477 continue; 478 default: 479 prompt_Printf(prompt, "Child failed (%s)\n", 480 ex_desc((int)c)); 481 log_Printf(LogPHASE, "Parent: Child failed (%s)\n", 482 ex_desc((int) c)); 483 } 484 break; 485 } 486 if (ret != 1) { 487 prompt_Printf(prompt, "Child exit, no status.\n"); 488 log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 489 } 490 close(bgpipe[0]); 491 } 492 return c; 493 } else if (sw.mode == PHYS_BACKGROUND) { 494 close(bgpipe[0]); 495 bundle->notify.fd = bgpipe[1]; 496 } 497 498 bundle_ChangedPID(bundle); 499 bundle_LockTun(bundle); /* we have a new pid */ 500 } 501 502 /* -auto, -dedicated, -ddial, -foreground & -background */ 503 prompt_Destroy(prompt, 0); 504 close(STDOUT_FILENO); 505 close(STDERR_FILENO); 506 close(STDIN_FILENO); 507 if (!sw.fg) 508 setsid(); 509 } else { 510 /* -direct - STDIN_FILENO gets used by physical_Open */ 511 prompt_TtyInit(NULL); 512 close(STDOUT_FILENO); 513 close(STDERR_FILENO); 514 } 515 } else { 516 /* -interactive */ 517 close(STDERR_FILENO); 518 prompt_TtyInit(prompt); 519 prompt_TtyCommandMode(prompt); 520 prompt_Required(prompt); 521 } 522 523 /* We can get rid of these now */ 524 for (f = 0; f < sizeof holdfd / sizeof *holdfd; f++) 525 close(holdfd[f]); 526 527 log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(sw.mode)); 528 DoLoop(bundle); 529 AbortProgram(EX_NORMAL); 530 531 return EX_NORMAL; 532 } 533 534 static void 535 DoLoop(struct bundle *bundle) 536 { 537 fd_set *rfds, *wfds, *efds; 538 int i, nfds, nothing_done; 539 540 if ((rfds = mkfdset()) == NULL) { 541 log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 542 return; 543 } 544 545 if ((wfds = mkfdset()) == NULL) { 546 log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 547 free(rfds); 548 return; 549 } 550 551 if ((efds = mkfdset()) == NULL) { 552 log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 553 free(rfds); 554 free(wfds); 555 return; 556 } 557 558 for (; !bundle_IsDead(bundle); bundle_CleanDatalinks(bundle)) { 559 nfds = 0; 560 zerofdset(rfds); 561 zerofdset(wfds); 562 zerofdset(efds); 563 564 /* All our datalinks, the tun device and the MP socket */ 565 descriptor_UpdateSet(&bundle->desc, rfds, wfds, efds, &nfds); 566 567 /* All our prompts and the diagnostic socket */ 568 descriptor_UpdateSet(&server.desc, rfds, NULL, NULL, &nfds); 569 570 bundle_CleanDatalinks(bundle); 571 if (bundle_IsDead(bundle)) 572 /* Don't select - we'll be here forever */ 573 break; 574 575 /* 576 * It's possible that we've had a signal since we last checked. If 577 * we don't check again before calling select(), we may end up stuck 578 * after having missed the event.... sig_Handle() tries to be as 579 * quick as possible if nothing is likely to have happened. 580 * This is only really likely if we block in open(... O_NONBLOCK) 581 * which will happen with a misconfigured device. 582 */ 583 if (sig_Handle()) 584 continue; 585 586 i = select(nfds, rfds, wfds, efds, NULL); 587 588 if (i < 0 && errno != EINTR) { 589 log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 590 if (log_IsKept(LogTIMER)) { 591 struct timeval t; 592 593 for (i = 0; i <= nfds; i++) { 594 if (FD_ISSET(i, rfds)) { 595 log_Printf(LogTIMER, "Read set contains %d\n", i); 596 FD_CLR(i, rfds); 597 t.tv_sec = t.tv_usec = 0; 598 if (select(nfds, rfds, wfds, efds, &t) != -1) { 599 log_Printf(LogTIMER, "The culprit !\n"); 600 break; 601 } 602 } 603 if (FD_ISSET(i, wfds)) { 604 log_Printf(LogTIMER, "Write set contains %d\n", i); 605 FD_CLR(i, wfds); 606 t.tv_sec = t.tv_usec = 0; 607 if (select(nfds, rfds, wfds, efds, &t) != -1) { 608 log_Printf(LogTIMER, "The culprit !\n"); 609 break; 610 } 611 } 612 if (FD_ISSET(i, efds)) { 613 log_Printf(LogTIMER, "Error set contains %d\n", i); 614 FD_CLR(i, efds); 615 t.tv_sec = t.tv_usec = 0; 616 if (select(nfds, rfds, wfds, efds, &t) != -1) { 617 log_Printf(LogTIMER, "The culprit !\n"); 618 break; 619 } 620 } 621 } 622 } 623 break; 624 } 625 626 log_Printf(LogTIMER, "Select returns %d\n", i); 627 628 sig_Handle(); 629 630 if (i <= 0) 631 continue; 632 633 for (i = 0; i <= nfds; i++) 634 if (FD_ISSET(i, efds)) { 635 log_Printf(LogPHASE, "Exception detected on descriptor %d\n", i); 636 /* We deal gracefully with link descriptor exceptions */ 637 if (!bundle_Exception(bundle, i)) { 638 log_Printf(LogERROR, "Exception cannot be handled !\n"); 639 break; 640 } 641 } 642 643 if (i <= nfds) 644 break; 645 646 nothing_done = 1; 647 648 if (descriptor_IsSet(&server.desc, rfds)) { 649 descriptor_Read(&server.desc, bundle, rfds); 650 nothing_done = 0; 651 } 652 653 if (descriptor_IsSet(&bundle->desc, rfds)) { 654 descriptor_Read(&bundle->desc, bundle, rfds); 655 nothing_done = 0; 656 } 657 658 if (descriptor_IsSet(&bundle->desc, wfds)) 659 if (descriptor_Write(&bundle->desc, bundle, wfds) <= 0 && nothing_done) { 660 /* 661 * This is disastrous. The OS has told us that something is 662 * writable, and all our write()s have failed. Rather than 663 * going back immediately to do our UpdateSet()s and select(), 664 * we sleep for a bit to avoid gobbling up all cpu time. 665 */ 666 struct timeval t; 667 668 t.tv_sec = 0; 669 t.tv_usec = 100000; 670 select(0, NULL, NULL, NULL, &t); 671 } 672 } 673 674 log_Printf(LogDEBUG, "DoLoop done.\n"); 675 } 676