1 /* 2 * PPP User command processing module 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id:$ 21 * 22 */ 23 #include <ctype.h> 24 #include "fsm.h" 25 #include "phase.h" 26 #include "lcp.h" 27 #include "ipcp.h" 28 #include "modem.h" 29 #include "command.h" 30 #include "hdlc.h" 31 #include "vars.h" 32 #include <netdb.h> 33 #include <sys/socket.h> 34 #include <arpa/inet.h> 35 #include <net/route.h> 36 #include "os.h" 37 38 extern int MakeArgs(); 39 extern void Cleanup(), TtyTermMode(), PacketMode(); 40 extern int EnableCommand(), DisableCommand(), DisplayCommand(); 41 extern int AcceptCommand(), DenyCommand(); 42 extern int LoadCommand(), SaveCommand(); 43 extern int ChangeParity(char *); 44 extern int SelectSystem(); 45 extern int ShowRoute(); 46 47 struct in_addr ifnetmask; 48 49 static int ShowCommand(), TerminalCommand(), QuitCommand(); 50 static int CloseCommand(), DialCommand(), DownCommand(); 51 static int SetCommand(), AddCommand(), DeleteCommand(); 52 53 static int 54 HelpCommand(list, argc, argv, plist) 55 struct cmdtab *list; 56 int argc; 57 char **argv; 58 struct cmdtab *plist; 59 { 60 struct cmdtab *cmd; 61 int n; 62 char c; 63 64 if (argc > 0) { 65 for (cmd = plist; cmd->name; cmd++) { 66 if (strcmp(cmd->name, *argv) == 0) { 67 printf("%s %s\n", cmd->name, cmd->syntax); 68 return(1); 69 } 70 } 71 return(1); 72 } 73 n = 0; 74 for (cmd = plist; cmd->func; cmd++) { 75 c = (n & 1)? '\n' : '\t'; 76 if (cmd->name) { 77 printf(" %-8s: %-20s%c", cmd->name, cmd->helpmes, c); 78 n++; 79 } 80 } 81 if (n & 1) 82 printf("\n"); 83 return(1); 84 } 85 86 int 87 IsInteractive() 88 { 89 char *mes = NULL; 90 91 if (mode & MODE_AUTO) 92 mes = "Working as auto mode."; 93 else if (mode & MODE_DIRECT) 94 mes = "Working as direct mode."; 95 else if (mode & MODE_DEDICATED) 96 mes = "Workring as dedicated mode."; 97 if (mes) { 98 printf("%s\n", mes); 99 return(0); 100 } 101 return(1); 102 } 103 104 static int 105 DialCommand(cmdlist, argc, argv) 106 struct cmdtab *cmdlist; 107 int argc; 108 char **argv; 109 { 110 if (LcpFsm.state > ST_CLOSED) { 111 printf("LCP state is [%s]\n", StateNames[LcpFsm.state]); 112 return(1); 113 } 114 if (!IsInteractive()) 115 return(1); 116 modem = OpenModem(mode); 117 if (modem < 0) { 118 printf("failed to open modem.\n"); 119 modem = 0; 120 return(1); 121 } 122 if (argc > 0) { 123 if (SelectSystem(*argv, CONFFILE) < 0) { 124 printf("%s: not found.\n", *argv); 125 return(1); 126 } 127 } 128 if (DialModem()) { 129 sleep(1); 130 ModemTimeout(); 131 PacketMode(); 132 } 133 return(1); 134 } 135 136 static char StrOption[] = "option .."; 137 static char StrRemote[] = "[remote]"; 138 char StrNull[] = ""; 139 140 struct cmdtab Commands[] = { 141 { "accept", NULL, AcceptCommand, 142 "accept option request", StrOption }, 143 { "add", NULL, AddCommand, 144 "add route", "dest mask gateway" }, 145 { "close", NULL, CloseCommand, 146 "Close connection", StrNull }, 147 { "delete", NULL, DeleteCommand, 148 "delete route", "dest gateway" }, 149 { "deny", NULL, DenyCommand, 150 "Deny option request", StrOption }, 151 { "dial", "call", DialCommand, 152 "Dial and login", StrRemote }, 153 { "disable", NULL, DisableCommand, 154 "Disable option", StrOption }, 155 { "display", NULL, DisplayCommand, 156 "Display option configs", StrNull }, 157 { "enable", NULL, EnableCommand, 158 "Enable option", StrOption }, 159 { "load", NULL, LoadCommand, 160 "Load settings", StrRemote }, 161 { "save", NULL, SaveCommand, 162 "Save settings", StrNull }, 163 { "set", "setup", SetCommand, 164 "Set parameters", "var value" }, 165 { "show", NULL, ShowCommand, 166 "Show status and statictics", "var" }, 167 { "term", NULL, TerminalCommand, 168 "Enter to terminal mode", StrNull }, 169 { "quit", "bye", QuitCommand, 170 "Quit PPP program", StrNull }, 171 { "help", "?", HelpCommand, 172 "Display this message", "[command]", (void *)Commands }, 173 { NULL, "down", DownCommand, 174 "Generate down event", StrNull }, 175 { NULL, NULL, NULL }, 176 }; 177 178 extern int ReportCcpStatus(); 179 extern int ReportLcpStatus(); 180 extern int ReportIpcpStatus(); 181 extern int ReportProtStatus(); 182 extern int ReportCompress(); 183 extern int ShowModemStatus(); 184 extern int ReportHdlcStatus(); 185 extern int ShowMemMap(); 186 187 static char *LogLevelName[] = { 188 LM_PHASE, LM_CHAT, LM_LQM, LM_LCP, 189 LM_TCPIP, LM_HDLC, LM_ASYNC, 190 }; 191 192 static int ShowDebugLevel() 193 { 194 int i; 195 196 printf("%02x: ", loglevel); 197 for (i = LOG_PHASE; i < MAXLOGLEVEL; i++) { 198 if (loglevel & (1 << i)) 199 printf("%s ", LogLevelName[i]); 200 } 201 printf("\n"); 202 return(1); 203 } 204 205 static int ShowEscape() 206 { 207 int code, bit; 208 209 if (EscMap[32]) { 210 for (code = 0; code < 32; code++) { 211 if (EscMap[code]) { 212 for (bit = 0; bit < 8; bit++) { 213 if (EscMap[code] & (1<<bit)) { 214 printf(" 0x%02x", (code << 3) + bit); 215 } 216 } 217 } 218 } 219 printf("\n"); 220 } 221 return(1); 222 } 223 224 static int ShowTimeout() 225 { 226 printf(" Idle Timer: %d secs LQR Timer: %d secs\n", 227 VarIdleTimeout, VarLqrTimeout); 228 return(1); 229 } 230 231 static int ShowAuthKey() 232 { 233 printf("AuthName = %s\n", VarAuthName); 234 printf("AuthKey = %s\n", VarAuthKey); 235 return(1); 236 } 237 238 static int ShowVersion() 239 { 240 extern char *VarVersion[]; 241 242 printf("%s\n", VarVersion); 243 return(1); 244 } 245 246 static int ShowLogList() 247 { 248 ListLog(); 249 return(1); 250 } 251 252 extern int ShowIfilter(), ShowOfilter(), ShowDfilter(); 253 254 struct cmdtab ShowCommands[] = { 255 { "auth", NULL, ShowAuthKey, "Show auth name/key", 256 StrNull, }, 257 { "ccp", NULL, ReportCcpStatus, "Show CCP status", 258 StrNull, }, 259 { "compress", NULL, ReportCompress, "Show compression statictics", 260 StrNull }, 261 { "debug", NULL, ShowDebugLevel, "Show current debug level", 262 StrNull }, 263 { "dfilter", NULL, ShowDfilter, "Show Demand filters", 264 StrOption }, 265 { "escape", NULL, ShowEscape, "Show escape characters", 266 StrNull }, 267 { "hdlc", NULL, ReportHdlcStatus, "Show HDLC error summary", 268 StrNull }, 269 { "ifilter", NULL, ShowIfilter, "Show Input filters", 270 StrOption }, 271 { "ipcp", NULL, ReportIpcpStatus, "Show IPCP status", 272 StrNull, }, 273 { "lcp", NULL, ReportLcpStatus, "Show LCP status", 274 StrNull, }, 275 { "log", NULL, ShowLogList, "Show log records", 276 StrNull, }, 277 { "mem", NULL, ShowMemMap, "Show memory map", 278 StrNull, }, 279 { "modem", NULL, ShowModemStatus, "Show modem setups", 280 StrNull, }, 281 { "ofilter", NULL, ShowOfilter, "Show Output filters", 282 StrOption }, 283 { "proto", NULL, ReportProtStatus, "Show protocol summary", 284 StrNull, }, 285 { "route", NULL, ShowRoute, "Show routing table", 286 StrNull, }, 287 { "timeout", NULL, ShowTimeout, "Show Idle timeout value", 288 StrNull, }, 289 { "version", NULL, ShowVersion, "Show version string", 290 StrNull, }, 291 { "help", "?", HelpCommand, "Display this message", 292 StrNull, (void *)ShowCommands }, 293 { NULL, NULL, NULL }, 294 }; 295 296 struct cmdtab * 297 FindCommand(cmds, str, pmatch) 298 struct cmdtab *cmds; 299 char *str; 300 int *pmatch; 301 { 302 int nmatch = 0; 303 int len = strlen(str); 304 struct cmdtab *found = NULL; 305 306 while (cmds->func) { 307 if (cmds->name && strncmp(str, cmds->name, len) == 0) { 308 nmatch++; 309 found = cmds; 310 } else if (cmds->alias && strncmp(str, cmds->alias, len) == 0) { 311 nmatch++; 312 found = cmds; 313 } 314 cmds++; 315 } 316 *pmatch = nmatch; 317 return(found); 318 } 319 320 int 321 FindExec(cmdlist, argc, argv) 322 struct cmdtab *cmdlist; 323 int argc; 324 char **argv; 325 { 326 struct cmdtab *cmd; 327 int val = 1; 328 int nmatch; 329 330 cmd = FindCommand(cmdlist, *argv, &nmatch); 331 if (nmatch > 1) 332 printf("Anbiguous.\n"); 333 else if (cmd) 334 val = (cmd->func)(cmd, --argc, ++argv, cmd->args); 335 else 336 printf("what?\n"); 337 return(val); 338 } 339 340 void 341 Prompt(flag) 342 int flag; 343 { 344 if (!(mode & MODE_INTER)) 345 return; 346 if (flag) printf("\n"); 347 if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK) 348 printf("PPP> "); 349 else 350 printf("ppp> "); 351 fflush(stdout); 352 } 353 354 void 355 DecodeCommand(buff, nb, prompt) 356 char *buff; 357 int nb; 358 int prompt; 359 { 360 char *vector[20]; 361 char **argv; 362 int argc, val; 363 char *cp; 364 365 val = 1; 366 if (nb > 0) { 367 cp = buff + strcspn(buff, "\r\n"); 368 if (cp) 369 *cp = '\0'; 370 { 371 argc = MakeArgs(buff, &vector); 372 argv = vector; 373 374 if (argc > 0) 375 val = FindExec(Commands, argc, argv); 376 } 377 } 378 if (val && prompt) 379 Prompt(0); 380 } 381 382 static int 383 ShowCommand(list, argc, argv) 384 struct cmdtab *list; 385 int argc; 386 char **argv; 387 { 388 int val = 1; 389 390 if (argc > 0) 391 val = FindExec(ShowCommands, argc, argv); 392 else 393 printf("Use ``show ?'' to get a list.\n"); 394 return(val); 395 } 396 397 static int 398 TerminalCommand() 399 { 400 if (LcpFsm.state > ST_CLOSED) { 401 printf("LCP state is [%s]\n", StateNames[LcpFsm.state]); 402 return(1); 403 } 404 if (!IsInteractive()) 405 return(1); 406 modem = OpenModem(mode); 407 if (modem < 0) { 408 printf("failed to open modem.\n"); 409 modem = 0; 410 return(1); 411 } 412 printf("Enter to terminal mode.\n"); 413 printf("Type `~?' for help.\n"); 414 TtyTermMode(); 415 return(0); 416 } 417 418 static int 419 QuitCommand(list, argc, argv) 420 struct cmdtab *list; 421 int argc; 422 char **argv; 423 { 424 if (mode & (MODE_DIRECT|MODE_DEDICATED|MODE_AUTO)) { 425 if (argc > 0) { 426 Cleanup(EX_NORMAL); 427 } else { 428 close(netfd); 429 close(1); 430 netfd = -1; 431 mode &= ~MODE_INTER; 432 } 433 } else 434 Cleanup(EX_NORMAL); 435 return(1); 436 } 437 438 static int 439 CloseCommand() 440 { 441 LcpClose(); 442 return(1); 443 } 444 445 static int 446 DownCommand() 447 { 448 LcpDown(); 449 return(1); 450 } 451 452 static int validspeed[] = { 453 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 0 454 }; 455 456 static int SetModemSpeed(list, argc, argv) 457 struct cmdtab *list; 458 int argc; 459 char **argv; 460 { 461 int speed; 462 int *sp; 463 464 if (argc > 0) { 465 speed = atoi(*argv); 466 for (sp = validspeed; *sp; sp++) { 467 if (*sp == speed) { 468 VarSpeed = speed; 469 return(1); 470 } 471 } 472 printf("invalid speed.\n"); 473 } 474 return(1); 475 } 476 477 static int SetModemParity(list, argc, argv) 478 struct cmdtab *list; 479 int argc; 480 char **argv; 481 { 482 int parity; 483 484 if (argc > 0) { 485 parity = ChangeParity(*argv); 486 if (parity < 0) 487 printf("Invalid parity.\n"); 488 else 489 VarParity = parity; 490 } 491 return(1); 492 } 493 494 static int 495 SetDebugLevel(list, argc, argv) 496 struct cmdtab *list; 497 int argc; 498 char **argv; 499 { 500 int level, w; 501 502 for (level = 0; argc-- > 0; argv++) { 503 if (isdigit(**argv)) { 504 w = atoi(*argv); 505 if (w < 0 || w >= MAXLOGLEVEL) { 506 printf("invalid log level.\n"); 507 break; 508 } else 509 level |= (1 << w); 510 } else { 511 for (w = 0; w < MAXLOGLEVEL; w++) { 512 if (strcasecmp(*argv, LogLevelName[w]) == 0) { 513 level |= (1 << w); 514 continue; 515 } 516 } 517 } 518 } 519 loglevel = level; 520 return(1); 521 } 522 523 static int 524 SetEscape(list, argc, argv) 525 struct cmdtab *list; 526 int argc; 527 char **argv; 528 { 529 int code; 530 531 for (code = 0; code < 33; code++) 532 EscMap[code] = 0; 533 while (argc-- > 0) { 534 sscanf(*argv++, "%x", &code); 535 code &= 0xff; 536 EscMap[code >> 3] |= (1 << (code&7)); 537 EscMap[32] = 1; 538 } 539 return(1); 540 } 541 542 static int 543 SetInitialMRU(list, argc, argv) 544 struct cmdtab *list; 545 int argc; 546 char **argv; 547 { 548 int mru; 549 550 if (argc > 0) { 551 mru = atoi(*argv); 552 if (mru < 100) 553 printf("given value is too small.\n"); 554 else if (mru > MAX_MRU) 555 printf("given value is too big.\n"); 556 else 557 VarMRU = mru; 558 } 559 return(1); 560 } 561 562 static int 563 SetIdleTimeout(list, argc, argv) 564 struct cmdtab *list; 565 int argc; 566 char **argv; 567 { 568 if (argc-- > 0) { 569 VarIdleTimeout = atoi(*argv++); 570 if (argc > 0) 571 VarLqrTimeout = atoi(*argv); 572 } 573 return(1); 574 } 575 576 struct in_addr 577 GetIpAddr(cp) 578 char *cp; 579 { 580 struct hostent *hp; 581 struct in_addr ipaddr; 582 583 hp = gethostbyname(cp); 584 if (hp && hp->h_addrtype == AF_INET) 585 bcopy(hp->h_addr, &ipaddr, hp->h_length); 586 else if (inet_aton(cp, &ipaddr) == 0) 587 ipaddr.s_addr = 0; 588 return(ipaddr); 589 } 590 591 static int 592 SetInterfaceAddr(list, argc, argv) 593 struct cmdtab *list; 594 int argc; 595 char **argv; 596 { 597 int width; 598 599 DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L; 600 if (argc > 0) { 601 ParseAddr(argc, argv++, 602 &DefMyAddress.ipaddr, &DefMyAddress.mask, &DefMyAddress.width); 603 if (--argc > 0) { 604 ParseAddr(argc, argv++, 605 &DefHisAddress.ipaddr, &DefHisAddress.mask, &DefHisAddress.width); 606 if (--argc > 0) { 607 ifnetmask = GetIpAddr(*argv); 608 } 609 } 610 } 611 /* 612 * For backwards compatibility, 0.0.0.0 means any address. 613 */ 614 if (DefMyAddress.ipaddr.s_addr == 0) { 615 DefMyAddress.mask.s_addr = 0; 616 DefMyAddress.width = 0; 617 } 618 if (DefHisAddress.ipaddr.s_addr == 0) { 619 DefHisAddress.mask.s_addr = 0; 620 DefHisAddress.width = 0; 621 } 622 623 if ((mode & MODE_AUTO) | 624 ((mode & MODE_DEDICATED) && dstsystem)) { 625 OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask); 626 } 627 return(1); 628 } 629 630 631 #define VAR_AUTHKEY 0 632 #define VAR_DIAL 1 633 #define VAR_LOGIN 2 634 #define VAR_AUTHNAME 3 635 #define VAR_DEVICE 4 636 #define VAR_ACCMAP 5 637 #define VAR_PHONE 6 638 639 static int 640 SetVariable(list, argc, argv, param) 641 struct cmdtab *list; 642 int argc; 643 char **argv; 644 int param; 645 { 646 u_long map; 647 648 if (argc > 0) { 649 switch (param) { 650 case VAR_AUTHKEY: 651 strncpy(VarAuthKey, *argv, sizeof(VarAuthKey)-1); 652 break; 653 case VAR_AUTHNAME: 654 strncpy(VarAuthName, *argv, sizeof(VarAuthName)-1); 655 break; 656 case VAR_DIAL: 657 strncpy(VarDialScript, *argv, sizeof(VarDialScript)-1); 658 break; 659 case VAR_LOGIN: 660 strncpy(VarLoginScript, *argv, sizeof(VarDialScript)-1); 661 break; 662 case VAR_DEVICE: 663 strncpy(VarDevice, *argv, sizeof(VarDevice)-1); 664 break; 665 case VAR_ACCMAP: 666 sscanf(*argv, "%x", &map); 667 VarAccmap = map; 668 break; 669 case VAR_PHONE: 670 strncpy(VarPhone, *argv, sizeof(VarPhone)-1); 671 break; 672 } 673 } 674 return(1); 675 } 676 677 static int SetOpenMode(list, argc, argv) 678 struct cmdtab *list; 679 int argc; 680 char **argv; 681 { 682 if (argc > 0) { 683 if (strcmp(*argv, "active") == 0) 684 VarOpenMode = OPEN_ACTIVE; 685 else if (strcmp(*argv, "passive") == 0) 686 VarOpenMode = OPEN_PASSIVE; 687 else 688 printf("Invalid mode.\n"); 689 } 690 return(1); 691 } 692 693 static char StrChatStr[] = "chat-script"; 694 static char StrValue[] = "value"; 695 696 extern int SetIfilter(), SetOfilter(), SetDfilter(); 697 698 struct cmdtab SetCommands[] = { 699 { "accmap", NULL, SetVariable, "Set accmap value", 700 "hex-value", (void *)VAR_ACCMAP }, 701 { "authkey", "key", SetVariable, "Set authentication key", 702 "key", (void *)VAR_AUTHKEY }, 703 { "authname", NULL, SetVariable, "Set authentication name", 704 "name", (void *)VAR_AUTHNAME }, 705 { "debug", NULL, SetDebugLevel, "Set debug level", 706 StrValue }, 707 { "device", "line", SetVariable, "Set modem device name", 708 "device-name", (void *)VAR_DEVICE }, 709 { "dfilter", NULL, SetDfilter, "Set demand filter", 710 "..." }, 711 { "dial", NULL, SetVariable, "Set dialing script", 712 StrChatStr, (void *)VAR_DIAL }, 713 { "escape", NULL, SetEscape, "Set escape characters", 714 "hex-digit ..."}, 715 { "ifaddr", NULL, SetInterfaceAddr, "Set destination address", 716 "src-addr dst-addr netmask" }, 717 { "ifilter", NULL, SetIfilter, "Set input filter", 718 "..." }, 719 { "login", NULL, SetVariable, "Set login script", 720 StrChatStr, (void *)VAR_LOGIN }, 721 { "mru", "mtu", SetInitialMRU, "Set Initial MRU value", 722 StrValue }, 723 { "ofilter", NULL, SetOfilter, "Set output filter", 724 "..." }, 725 { "openmode", NULL, SetOpenMode, "Set open mode", 726 "[active|passive]" }, 727 { "parity", NULL, SetModemParity, "Set modem parity", 728 "[odd|even|none]" }, 729 { "phone", NULL, SetVariable, "Set telephone number", 730 "phone-number", (void *)VAR_PHONE }, 731 { "speed", NULL, SetModemSpeed, "Set modem speed", 732 "speed" }, 733 { "timeout", NULL, SetIdleTimeout, "Set Idle timeout", 734 StrValue }, 735 { "help", "?", HelpCommand, "Display this message", 736 StrNull, (void *)SetCommands }, 737 { NULL, NULL, NULL }, 738 }; 739 740 static int 741 SetCommand(list, argc, argv) 742 struct cmdtab *list; 743 int argc; 744 char **argv; 745 { 746 int val = 1; 747 748 if (argc > 0) 749 val = FindExec(SetCommands, argc, argv); 750 else 751 printf("Use ``set ?'' to get a list.\n"); 752 return(val); 753 } 754 755 756 static int 757 AddCommand(list, argc, argv) 758 struct cmdtab *list; 759 int argc; 760 char **argv; 761 { 762 struct in_addr dest, gateway, netmask; 763 764 if (argc == 3) { 765 dest = GetIpAddr(argv[0]); 766 netmask = GetIpAddr(argv[1]); 767 if (strcmp(argv[2], "HISADDR") == 0) 768 gateway = IpcpInfo.his_ipaddr; 769 else 770 gateway = GetIpAddr(argv[2]); 771 OsSetRoute(RTM_ADD, dest, gateway, netmask); 772 } else { 773 printf("Usage: %s %s\n", list->name, list->syntax); 774 } 775 return(1); 776 } 777 778 static int 779 DeleteCommand(list, argc, argv) 780 struct cmdtab *list; 781 int argc; 782 char **argv; 783 { 784 struct in_addr dest, gateway, netmask; 785 786 if (argc >= 2) { 787 dest = GetIpAddr(argv[0]); 788 if (strcmp(argv[1], "HISADDR") == 0) 789 gateway = IpcpInfo.his_ipaddr; 790 else 791 gateway = GetIpAddr(argv[1]); 792 netmask.s_addr = 0; 793 if (argc == 3) { 794 if (inet_aton(argv[1], &netmask) == 0) { 795 printf("bad netmask value.\n"); 796 return(1); 797 } 798 } 799 OsSetRoute(RTM_DELETE, dest, gateway, netmask); 800 } else if (argc == 1 && strcmp(argv[0], "ALL") == 0) { 801 DeleteIfRoutes(0); 802 } else { 803 printf("Usage: %s %s\n", list->name, list->syntax); 804 } 805 return(1); 806 } 807 808