command.c revision 6059
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 38extern int MakeArgs(); 39extern void Cleanup(), TtyTermMode(), PacketMode(); 40extern int EnableCommand(), DisableCommand(), DisplayCommand(); 41extern int AcceptCommand(), DenyCommand(); 42extern int LoadCommand(), SaveCommand(); 43extern int ChangeParity(char *); 44extern int SelectSystem(); 45extern int ShowRoute(); 46 47struct in_addr ifnetmask; 48 49static int ShowCommand(), TerminalCommand(), QuitCommand(); 50static int CloseCommand(), DialCommand(), DownCommand(); 51static int SetCommand(), AddCommand(), DeleteCommand(); 52 53static int 54HelpCommand(list, argc, argv, plist) 55struct cmdtab *list; 56int argc; 57char **argv; 58struct 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 86int 87IsInteractive() 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 104static int 105DialCommand(cmdlist, argc, argv) 106struct cmdtab *cmdlist; 107int argc; 108char **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 136static char StrOption[] = "option .."; 137static char StrRemote[] = "[remote]"; 138char StrNull[] = ""; 139 140struct 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 178extern int ReportCcpStatus(); 179extern int ReportLcpStatus(); 180extern int ReportIpcpStatus(); 181extern int ReportProtStatus(); 182extern int ReportCompress(); 183extern int ShowModemStatus(); 184extern int ReportHdlcStatus(); 185extern int ShowMemMap(); 186 187static char *LogLevelName[] = { 188 LM_PHASE, LM_CHAT, LM_LQM, LM_LCP, 189 LM_TCPIP, LM_HDLC, LM_ASYNC, 190}; 191 192static 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 205static 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 224static int ShowTimeout() 225{ 226 printf(" Idle Timer: %d secs LQR Timer: %d secs\n", 227 VarIdleTimeout, VarLqrTimeout); 228 return(1); 229} 230 231static int ShowAuthKey() 232{ 233 printf("AuthName = %s\n", VarAuthName); 234 printf("AuthKey = %s\n", VarAuthKey); 235 return(1); 236} 237 238static int ShowVersion() 239{ 240 extern char *VarVersion[]; 241 242 printf("%s\n", VarVersion); 243 return(1); 244} 245 246static int ShowLogList() 247{ 248 ListLog(); 249 return(1); 250} 251 252extern int ShowIfilter(), ShowOfilter(), ShowDfilter(); 253 254struct 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 296struct cmdtab * 297FindCommand(cmds, str, pmatch) 298struct cmdtab *cmds; 299char *str; 300int *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 320int 321FindExec(cmdlist, argc, argv) 322struct cmdtab *cmdlist; 323int argc; 324char **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 340void 341Prompt(flag) 342int 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 354void 355DecodeCommand(buff, nb, prompt) 356char *buff; 357int nb; 358int 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 382static int 383ShowCommand(list, argc, argv) 384struct cmdtab *list; 385int argc; 386char **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 397static int 398TerminalCommand() 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 418static int 419QuitCommand(list, argc, argv) 420struct cmdtab *list; 421int argc; 422char **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 438static int 439CloseCommand() 440{ 441 LcpClose(); 442 return(1); 443} 444 445static int 446DownCommand() 447{ 448 LcpDown(); 449 return(1); 450} 451 452static int validspeed[] = { 453 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 0 454}; 455 456static int SetModemSpeed(list, argc, argv) 457struct cmdtab *list; 458int argc; 459char **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 477static int SetModemParity(list, argc, argv) 478struct cmdtab *list; 479int argc; 480char **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 494static int 495SetDebugLevel(list, argc, argv) 496struct cmdtab *list; 497int argc; 498char **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 523static int 524SetEscape(list, argc, argv) 525struct cmdtab *list; 526int argc; 527char **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 542static int 543SetInitialMRU(list, argc, argv) 544struct cmdtab *list; 545int argc; 546char **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 562static int 563SetIdleTimeout(list, argc, argv) 564struct cmdtab *list; 565int argc; 566char **argv; 567{ 568 if (argc-- > 0) { 569 VarIdleTimeout = atoi(*argv++); 570 if (argc > 0) 571 VarLqrTimeout = atoi(*argv); 572 } 573 return(1); 574} 575 576struct in_addr 577GetIpAddr(cp) 578char *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 591static int 592SetInterfaceAddr(list, argc, argv) 593struct cmdtab *list; 594int argc; 595char **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 639static int 640SetVariable(list, argc, argv, param) 641struct cmdtab *list; 642int argc; 643char **argv; 644int 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 677static int SetOpenMode(list, argc, argv) 678struct cmdtab *list; 679int argc; 680char **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 693static char StrChatStr[] = "chat-script"; 694static char StrValue[] = "value"; 695 696extern int SetIfilter(), SetOfilter(), SetDfilter(); 697 698struct 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 740static int 741SetCommand(list, argc, argv) 742struct cmdtab *list; 743int argc; 744char **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 756static int 757AddCommand(list, argc, argv) 758struct cmdtab *list; 759int argc; 760char **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 778static int 779DeleteCommand(list, argc, argv) 780struct cmdtab *list; 781int argc; 782char **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