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