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: command.c,v 1.131.2.56 1998/04/07 23:45:45 brian Exp $ 21 * 22 */ 23 #include <sys/types.h> 24 #include <netinet/in_systm.h> 25 #include <netinet/in.h> 26 #include <netinet/ip.h> 27 #include <arpa/inet.h> 28 #include <sys/socket.h> 29 #include <net/route.h> 30 #include <netdb.h> 31 #include <sys/un.h> 32 33 #ifndef NOALIAS 34 #include <alias.h> 35 #endif 36 #include <errno.h> 37 #include <fcntl.h> 38 #include <paths.h> 39 #include <signal.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <sys/wait.h> 44 #include <termios.h> 45 #include <unistd.h> 46 47 #include "command.h" 48 #include "mbuf.h" 49 #include "log.h" 50 #include "defs.h" 51 #include "timer.h" 52 #include "fsm.h" 53 #include "lcp.h" 54 #include "iplist.h" 55 #include "throughput.h" 56 #include "slcompress.h" 57 #include "ipcp.h" 58 #include "modem.h" 59 #ifndef NOALIAS 60 #include "alias_cmd.h" 61 #endif 62 #include "lqr.h" 63 #include "hdlc.h" 64 #include "loadalias.h" 65 #include "vars.h" 66 #include "systems.h" 67 #include "filter.h" 68 #include "descriptor.h" 69 #include "main.h" 70 #include "route.h" 71 #include "ccp.h" 72 #include "auth.h" 73 #include "async.h" 74 #include "link.h" 75 #include "physical.h" 76 #include "mp.h" 77 #include "bundle.h" 78 #include "server.h" 79 #include "prompt.h" 80 #include "chat.h" 81 #include "chap.h" 82 #include "datalink.h" 83 84 static const char *HIDDEN = "********"; 85 86 static int ShowCommand(struct cmdargs const *); 87 static int TerminalCommand(struct cmdargs const *); 88 static int QuitCommand(struct cmdargs const *); 89 static int CloseCommand(struct cmdargs const *); 90 static int DownCommand(struct cmdargs const *); 91 static int AllowCommand(struct cmdargs const *); 92 static int SetCommand(struct cmdargs const *); 93 static int LinkCommand(struct cmdargs const *); 94 static int AddCommand(struct cmdargs const *); 95 static int DeleteCommand(struct cmdargs const *); 96 #ifndef NOALIAS 97 static int AliasCommand(struct cmdargs const *); 98 static int AliasEnable(struct cmdargs const *); 99 static int AliasOption(struct cmdargs const *); 100 #endif 101 102 static int 103 HelpCommand(struct cmdargs const *arg) 104 { 105 struct cmdtab const *cmd; 106 int n, cmax, dmax, cols; 107 108 if (!arg->prompt) { 109 LogPrintf(LogWARN, "help: Cannot help without a prompt\n"); 110 return 0; 111 } 112 113 if (arg->argc > 0) { 114 for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 115 if ((cmd->lauth & arg->prompt->auth) && 116 ((cmd->name && !strcasecmp(cmd->name, *arg->argv)) || 117 (cmd->alias && !strcasecmp(cmd->alias, *arg->argv)))) { 118 prompt_Printf(arg->prompt, "%s\n", cmd->syntax); 119 return 0; 120 } 121 return -1; 122 } 123 124 cmax = dmax = 0; 125 for (cmd = arg->cmdtab; cmd->func; cmd++) 126 if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 127 if ((n = strlen(cmd->name)) > cmax) 128 cmax = n; 129 if ((n = strlen(cmd->helpmes)) > dmax) 130 dmax = n; 131 } 132 133 cols = 80 / (dmax + cmax + 3); 134 n = 0; 135 for (cmd = arg->cmdtab; cmd->func; cmd++) 136 if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 137 prompt_Printf(arg->prompt, " %-*.*s: %-*.*s", 138 cmax, cmax, cmd->name, dmax, dmax, cmd->helpmes); 139 if (++n % cols == 0) 140 prompt_Printf(arg->prompt, "\n"); 141 } 142 if (n % cols != 0) 143 prompt_Printf(arg->prompt, "\n"); 144 145 return 0; 146 } 147 148 static int 149 CloneCommand(struct cmdargs const *arg) 150 { 151 int f; 152 153 if (arg->argc == 0) 154 return -1; 155 156 if (!arg->bundle->ncp.mp.active) { 157 LogPrintf(LogWARN, "clone: Only available in multilink mode\n"); 158 return 1; 159 } 160 161 for (f = 0; f < arg->argc; f++) 162 bundle_DatalinkClone(arg->bundle, arg->cx, arg->argv[f]); 163 return 0; 164 } 165 166 static int 167 RemoveCommand(struct cmdargs const *arg) 168 { 169 if (arg->argc != 0) 170 return -1; 171 172 if (!arg->bundle->ncp.mp.active) { 173 LogPrintf(LogWARN, "remove: Only available in multilink mode\n"); 174 return 1; 175 } 176 177 if (arg->cx->state != DATALINK_CLOSED) { 178 LogPrintf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 179 return 2; 180 } 181 182 bundle_DatalinkRemove(arg->bundle, arg->cx); 183 return 0; 184 } 185 186 int 187 LoadCommand(struct cmdargs const *arg) 188 { 189 const char *name; 190 191 if (arg->argc > 0) 192 name = *arg->argv; 193 else 194 name = "default"; 195 196 if (!ValidSystem(name, arg->prompt, arg->bundle->phys_type)) { 197 LogPrintf(LogERROR, "%s: Label not allowed\n", name); 198 return 1; 199 } else if (SelectSystem(arg->bundle, name, CONFFILE, arg->prompt) < 0) { 200 LogPrintf(LogWARN, "%s: label not found.\n", name); 201 return -1; 202 } else 203 SetLabel(arg->argc ? name : NULL); 204 return 0; 205 } 206 207 int 208 SaveCommand(struct cmdargs const *arg) 209 { 210 LogPrintf(LogWARN, "save command is not implemented (yet).\n"); 211 return 1; 212 } 213 214 static int 215 DialCommand(struct cmdargs const *arg) 216 { 217 int res; 218 219 if ((arg->cx && !(arg->cx->physical->type & (PHYS_MANUAL|PHYS_DEMAND))) 220 || (!arg->cx && (arg->bundle->phys_type & ~(PHYS_MANUAL|PHYS_DEMAND)))) { 221 LogPrintf(LogWARN, 222 "Manual dial is only available in auto and interactive mode\n"); 223 return 1; 224 } 225 226 if (arg->argc > 0 && (res = LoadCommand(arg)) != 0) 227 return res; 228 229 bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 230 231 return 0; 232 } 233 234 static int 235 ShellCommand(struct cmdargs const *arg, int bg) 236 { 237 const char *shell; 238 pid_t shpid; 239 int argc; 240 char *argv[MAXARGS]; 241 242 #ifdef SHELL_ONLY_INTERACTIVELY 243 /* we're only allowed to shell when we run ppp interactively */ 244 if (arg->prompt && arg->prompt->owner) { 245 LogPrintf(LogWARN, "Can't start a shell from a network connection\n"); 246 return 1; 247 } 248 #endif 249 250 if (arg->argc == 0) 251 if (!arg->prompt) { 252 LogPrintf(LogWARN, "Can't start an interactive shell from" 253 " a config file\n"); 254 return 1; 255 } else if (arg->prompt->owner) { 256 LogPrintf(LogWARN, "Can't start an interactive shell from" 257 " a socket connection\n"); 258 return 1; 259 } else if (bg) { 260 LogPrintf(LogWARN, "Can only start an interactive shell in" 261 " the foreground mode\n"); 262 return 1; 263 } 264 265 if ((shpid = fork()) == 0) { 266 int dtablesize, i, fd; 267 268 if ((shell = getenv("SHELL")) == 0) 269 shell = _PATH_BSHELL; 270 271 TermTimerService(); 272 signal(SIGINT, SIG_DFL); 273 signal(SIGQUIT, SIG_DFL); 274 signal(SIGTERM, SIG_DFL); 275 signal(SIGHUP, SIG_DFL); 276 signal(SIGALRM, SIG_DFL); 277 278 if (arg->prompt) 279 fd = arg->prompt->fd_out; 280 else if ((fd = open("/dev/null", O_RDWR)) == -1) { 281 LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno)); 282 exit(1); 283 } 284 for (i = 0; i < 3; i++) 285 dup2(fd, i); 286 287 for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++) 288 close(i); 289 290 setuid(geteuid()); 291 if (arg->argc > 0) { 292 /* substitute pseudo args */ 293 argv[0] = strdup(arg->argv[0]); 294 for (argc = 1; argc < arg->argc; argc++) { 295 if (strcasecmp(arg->argv[argc], "HISADDR") == 0) 296 argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.peer_ip)); 297 else if (strcasecmp(arg->argv[argc], "INTERFACE") == 0) 298 argv[argc] = strdup(arg->bundle->ifname); 299 else if (strcasecmp(arg->argv[argc], "MYADDR") == 0) 300 argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.my_ip)); 301 else 302 argv[argc] = strdup(arg->argv[argc]); 303 } 304 argv[argc] = NULL; 305 if (bg) { 306 pid_t p; 307 308 p = getpid(); 309 if (daemon(1, 1) == -1) { 310 LogPrintf(LogERROR, "%d: daemon: %s\n", p, strerror(errno)); 311 exit(1); 312 } 313 } else if (arg->prompt) 314 printf("ppp: Pausing until %s finishes\n", arg->argv[0]); 315 execvp(argv[0], argv); 316 } else { 317 if (arg->prompt) 318 printf("ppp: Pausing until %s finishes\n", shell); 319 prompt_TtyOldMode(arg->prompt); 320 execl(shell, shell, NULL); 321 } 322 323 LogPrintf(LogWARN, "exec() of %s failed\n", 324 arg->argc > 0 ? arg->argv[0] : shell); 325 exit(255); 326 } 327 328 if (shpid == (pid_t) - 1) 329 LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno)); 330 else { 331 int status; 332 waitpid(shpid, &status, 0); 333 } 334 335 if (arg->prompt && !arg->prompt->owner) 336 prompt_TtyCommandMode(arg->prompt); 337 338 return 0; 339 } 340 341 static int 342 BgShellCommand(struct cmdargs const *arg) 343 { 344 if (arg->argc == 0) 345 return -1; 346 return ShellCommand(arg, 1); 347 } 348 349 static int 350 FgShellCommand(struct cmdargs const *arg) 351 { 352 return ShellCommand(arg, 0); 353 } 354 355 static struct cmdtab const Commands[] = { 356 {"accept", NULL, AcceptCommand, LOCAL_AUTH, 357 "accept option request", "accept option .."}, 358 {"add", NULL, AddCommand, LOCAL_AUTH, 359 "add route", "add dest mask gateway", NULL}, 360 {NULL, "add!", AddCommand, LOCAL_AUTH, 361 "add or change route", "add! dest mask gateway", (void *)1}, 362 #ifndef NOALIAS 363 {"alias", NULL, AliasCommand, LOCAL_AUTH, 364 "alias control", "alias option [yes|no]"}, 365 #endif 366 {"allow", "auth", AllowCommand, LOCAL_AUTH, 367 "Allow ppp access", "allow users|modes ...."}, 368 {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 369 "Run a background command", "[!]bg command"}, 370 {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 371 "Clone a link", "clone newname..."}, 372 {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 373 "Close connection", "close"}, 374 {"delete", NULL, DeleteCommand, LOCAL_AUTH, 375 "delete route", "delete dest", NULL}, 376 {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 377 "delete a route if it exists", "delete! dest", (void *)1}, 378 {"deny", NULL, DenyCommand, LOCAL_AUTH, 379 "Deny option request", "deny option .."}, 380 {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 381 "Dial and login", "dial|call [remote]"}, 382 {"disable", NULL, DisableCommand, LOCAL_AUTH, 383 "Disable option", "disable option .."}, 384 {"display", NULL, DisplayCommand, LOCAL_AUTH, 385 "Display option configs", "display"}, 386 {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX, 387 "Generate a down event", "down"}, 388 {"enable", NULL, EnableCommand, LOCAL_AUTH, 389 "Enable option", "enable option .."}, 390 {"link", "datalink", LinkCommand, LOCAL_AUTH, 391 "Link specific commands", "link name command ..."}, 392 {"load", NULL, LoadCommand, LOCAL_AUTH, 393 "Load settings", "load [remote]"}, 394 {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 395 "Password for manipulation", "passwd LocalPassword"}, 396 {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 397 "Quit PPP program", "quit|bye [all]"}, 398 {"remove", NULL, RemoveCommand, LOCAL_AUTH | LOCAL_CX, 399 "Remove a link", "remove"}, 400 {"save", NULL, SaveCommand, LOCAL_AUTH, 401 "Save settings", "save"}, 402 {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 403 "Set parameters", "set[up] var value"}, 404 {"shell", "!", FgShellCommand, LOCAL_AUTH, 405 "Run a subshell", "shell|! [sh command]"}, 406 {"show", NULL, ShowCommand, LOCAL_AUTH, 407 "Show status and stats", "show var"}, 408 {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 409 "Enter terminal mode", "term"}, 410 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 411 "Display this message", "help|? [command]", Commands}, 412 {NULL, NULL, NULL}, 413 }; 414 415 static int 416 ShowEscape(struct cmdargs const *arg) 417 { 418 if (arg->cx->physical->async.cfg.EscMap[32]) { 419 int code, bit; 420 char *sep = ""; 421 422 for (code = 0; code < 32; code++) 423 if (arg->cx->physical->async.cfg.EscMap[code]) 424 for (bit = 0; bit < 8; bit++) 425 if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 426 prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 427 sep = ", "; 428 } 429 prompt_Printf(arg->prompt, "\n"); 430 } 431 return 0; 432 } 433 434 static int 435 ShowTimeout(struct cmdargs const *arg) 436 { 437 int remaining; 438 439 prompt_Printf(arg->prompt, "Idle Timer: %ds\n", 440 arg->bundle->cfg.idle_timeout); 441 remaining = bundle_RemainingIdleTime(arg->bundle); 442 if (remaining != -1) 443 prompt_Printf(arg->prompt, "Remaining: %ds\n", remaining); 444 445 return 0; 446 } 447 448 static int 449 ShowTimerList(struct cmdargs const *arg) 450 { 451 ShowTimers(0, arg->prompt); 452 return 0; 453 } 454 455 static int 456 ShowStopped(struct cmdargs const *arg) 457 { 458 prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 459 if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 460 prompt_Printf(arg->prompt, "Disabled"); 461 else 462 prompt_Printf(arg->prompt, "%ld secs", 463 arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 464 465 prompt_Printf(arg->prompt, ", CCP: "); 466 if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 467 prompt_Printf(arg->prompt, "Disabled"); 468 else 469 prompt_Printf(arg->prompt, "%ld secs", 470 arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 471 472 prompt_Printf(arg->prompt, "\n"); 473 474 return 0; 475 } 476 477 static int 478 ShowAuthKey(struct cmdargs const *arg) 479 { 480 prompt_Printf(arg->prompt, "AuthName = %s\n", arg->bundle->cfg.auth.name); 481 prompt_Printf(arg->prompt, "AuthKey = %s\n", HIDDEN); 482 return 0; 483 } 484 485 static int 486 ShowVersion(struct cmdargs const *arg) 487 { 488 static char VarVersion[] = "PPP Version 2.0-beta"; 489 static char VarLocalVersion[] = "$Date: 1998/04/07 23:45:45 $"; 490 491 prompt_Printf(arg->prompt, "%s - %s \n", VarVersion, VarLocalVersion); 492 return 0; 493 } 494 495 int 496 ShowProtocolStats(struct cmdargs const *arg) 497 { 498 struct link *l = ChooseLink(arg); 499 500 prompt_Printf(arg->prompt, "%s:\n", l->name); 501 link_ReportProtocolStatus(l, arg->prompt); 502 return 0; 503 } 504 505 506 #ifndef NOMSEXT 507 static int 508 ShowMSExt(struct cmdargs const *arg) 509 { 510 prompt_Printf(arg->prompt, " MS PPP extention values \n"); 511 prompt_Printf(arg->prompt, " Primary NS : %s\n", 512 inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns_entries[0])); 513 prompt_Printf(arg->prompt, " Secondary NS : %s\n", 514 inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns_entries[1])); 515 prompt_Printf(arg->prompt, " Primary NBNS : %s\n", 516 inet_ntoa(arg->bundle->ncp.ipcp.cfg.nbns_entries[0])); 517 prompt_Printf(arg->prompt, " Secondary NBNS : %s\n", 518 inet_ntoa(arg->bundle->ncp.ipcp.cfg.nbns_entries[1])); 519 520 return 0; 521 } 522 523 #endif 524 525 static struct cmdtab const ShowCommands[] = { 526 {"auth", NULL, ShowAuthKey, LOCAL_AUTH, 527 "Show auth details", "show auth"}, 528 {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 529 "Show CCP status", "show cpp"}, 530 {"compress", NULL, ReportCompress, LOCAL_AUTH, 531 "Show compression stats", "show compress"}, 532 {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 533 "Show escape characters", "show escape"}, 534 {"filter", NULL, ShowFilter, LOCAL_AUTH, 535 "Show packet filters", "show filter [in|out|dial|alive]"}, 536 {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 537 "Show HDLC errors", "show hdlc"}, 538 {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH, 539 "Show IPCP status", "show ipcp"}, 540 {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 541 "Show LCP status", "show lcp"}, 542 {"links", "link", bundle_ShowLinks, LOCAL_AUTH, 543 "Show available link names", "show links"}, 544 {"log", NULL, log_ShowLevel, LOCAL_AUTH, 545 "Show log levels", "show log"}, 546 {"mem", NULL, ShowMemMap, LOCAL_AUTH, 547 "Show memory map", "show mem"}, 548 {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 549 "Show modem setups", "show modem"}, 550 #ifndef NOMSEXT 551 {"msext", NULL, ShowMSExt, LOCAL_AUTH, 552 "Show MS PPP extentions", "show msext"}, 553 #endif 554 {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 555 "Show protocol summary", "show proto"}, 556 {"route", NULL, ShowRoute, LOCAL_AUTH, 557 "Show routing table", "show route"}, 558 {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 559 "Show STOPPED timeout", "show stopped"}, 560 {"timeout", NULL, ShowTimeout, LOCAL_AUTH, 561 "Show Idle timeout", "show timeout"}, 562 {"timers", NULL, ShowTimerList, LOCAL_AUTH, 563 "Show alarm timers", "show timers"}, 564 {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 565 "Show version string", "show version"}, 566 {"who", NULL, log_ShowWho, LOCAL_AUTH, 567 "Show client list", "show who"}, 568 {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 569 "Display this message", "show help|? [command]", ShowCommands}, 570 {NULL, NULL, NULL}, 571 }; 572 573 static struct cmdtab const * 574 FindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 575 { 576 int nmatch; 577 int len; 578 struct cmdtab const *found; 579 580 found = NULL; 581 len = strlen(str); 582 nmatch = 0; 583 while (cmds->func) { 584 if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 585 if (cmds->name[len] == '\0') { 586 *pmatch = 1; 587 return cmds; 588 } 589 nmatch++; 590 found = cmds; 591 } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 592 if (cmds->alias[len] == '\0') { 593 *pmatch = 1; 594 return cmds; 595 } 596 nmatch++; 597 found = cmds; 598 } 599 cmds++; 600 } 601 *pmatch = nmatch; 602 return found; 603 } 604 605 static int 606 FindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, 607 char const *const *argv, const char *prefix, struct prompt *prompt, 608 struct datalink *cx) 609 { 610 struct cmdtab const *cmd; 611 int val = 1; 612 int nmatch; 613 struct cmdargs arg; 614 615 cmd = FindCommand(cmds, *argv, &nmatch); 616 if (nmatch > 1) 617 LogPrintf(LogWARN, "%s%s: Ambiguous command\n", prefix, *argv); 618 else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 619 if ((cmd->lauth & LOCAL_CX) && !cx) 620 /* We've got no context, but we require it */ 621 cx = bundle2datalink(bundle, NULL); 622 623 if ((cmd->lauth & LOCAL_CX) && !cx) 624 LogPrintf(LogWARN, "%s%s: No context (use the `link' command)\n", 625 prefix, *argv); 626 else { 627 if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 628 LogPrintf(LogWARN, "%s%s: Redundant context (%s) ignored\n", 629 prefix, *argv, cx->name); 630 cx = NULL; 631 } 632 arg.cmdtab = cmds; 633 arg.cmd = cmd; 634 arg.argc = argc-1; 635 arg.argv = argv+1; 636 arg.bundle = bundle; 637 arg.cx = cx; 638 arg.prompt = prompt; 639 val = (cmd->func) (&arg); 640 } 641 } else 642 LogPrintf(LogWARN, "%s%s: Invalid command\n", prefix, *argv); 643 644 if (val == -1) 645 LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax); 646 else if (val) 647 LogPrintf(LogWARN, "%s%s: Failed %d\n", prefix, *argv, val); 648 649 return val; 650 } 651 652 void 653 InterpretCommand(char *buff, int nb, int *argc, char ***argv) 654 { 655 static char *vector[MAXARGS]; 656 char *cp; 657 658 if (nb > 0) { 659 cp = buff + strcspn(buff, "\r\n"); 660 if (cp) 661 *cp = '\0'; 662 *argc = MakeArgs(buff, vector, VECSIZE(vector)); 663 *argv = vector; 664 } else 665 *argc = 0; 666 } 667 668 static int 669 arghidden(int argc, char const *const *argv, int n) 670 { 671 /* Is arg n of the given command to be hidden from the log ? */ 672 673 /* set authkey xxxxx */ 674 /* set key xxxxx */ 675 if (n == 2 && !strncasecmp(argv[0], "se", 2) && 676 (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 677 return 1; 678 679 /* passwd xxxxx */ 680 if (n == 1 && !strncasecmp(argv[0], "p", 1)) 681 return 1; 682 683 return 0; 684 } 685 686 void 687 RunCommand(struct bundle *bundle, int argc, char const *const *argv, 688 struct prompt *prompt, const char *label) 689 { 690 if (argc > 0) { 691 if (LogIsKept(LogCOMMAND)) { 692 static char buf[LINE_LEN]; 693 int f, n; 694 695 *buf = '\0'; 696 if (label) { 697 strncpy(buf, label, sizeof buf - 3); 698 buf[sizeof buf - 3] = '\0'; 699 strcat(buf, ": "); 700 } 701 n = strlen(buf); 702 for (f = 0; f < argc; f++) { 703 if (n < sizeof buf - 1 && f) 704 buf[n++] = ' '; 705 if (arghidden(argc, argv, f)) 706 strncpy(buf+n, HIDDEN, sizeof buf - n - 1); 707 else 708 strncpy(buf+n, argv[f], sizeof buf - n - 1); 709 n += strlen(buf+n); 710 } 711 LogPrintf(LogCOMMAND, "%s\n", buf); 712 } 713 FindExec(bundle, Commands, argc, argv, "", prompt, NULL); 714 } 715 } 716 717 void 718 DecodeCommand(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 719 const char *label) 720 { 721 int argc; 722 char **argv; 723 724 InterpretCommand(buff, nb, &argc, &argv); 725 RunCommand(bundle, argc, (char const *const *)argv, prompt, label); 726 } 727 728 static int 729 ShowCommand(struct cmdargs const *arg) 730 { 731 if (!arg->prompt) 732 LogPrintf(LogWARN, "show: Cannot show without a prompt\n"); 733 else if (arg->argc > 0) 734 FindExec(arg->bundle, ShowCommands, arg->argc, arg->argv, "show ", 735 arg->prompt, arg->cx); 736 else 737 prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 738 739 return 0; 740 } 741 742 static int 743 TerminalCommand(struct cmdargs const *arg) 744 { 745 if (!arg->prompt) { 746 LogPrintf(LogWARN, "term: Need a prompt\n"); 747 return 1; 748 } 749 750 if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 751 prompt_Printf(arg->prompt, "LCP state is [%s]\n", 752 State2Nam(arg->cx->physical->link.lcp.fsm.state)); 753 return 1; 754 } 755 756 datalink_Up(arg->cx, 0, 0); 757 prompt_TtyTermMode(arg->prompt, arg->cx); 758 return 0; 759 } 760 761 static int 762 QuitCommand(struct cmdargs const *arg) 763 { 764 if (!arg->prompt || prompt_IsController(arg->prompt) || 765 (arg->argc > 0 && !strcasecmp(*arg->argv, "all") && 766 (arg->prompt->auth & LOCAL_AUTH))) 767 Cleanup(EX_NORMAL); 768 if (arg->prompt) 769 prompt_Destroy(arg->prompt, 1); 770 771 return 0; 772 } 773 774 static int 775 CloseCommand(struct cmdargs const *arg) 776 { 777 bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, 1); 778 return 0; 779 } 780 781 static int 782 DownCommand(struct cmdargs const *arg) 783 { 784 datalink_Down(arg->cx, 1); 785 return 0; 786 } 787 788 static int 789 SetModemSpeed(struct cmdargs const *arg) 790 { 791 long speed; 792 char *end; 793 794 if (arg->argc > 0 && **arg->argv) { 795 if (arg->argc > 1) { 796 LogPrintf(LogWARN, "SetModemSpeed: Too many arguments"); 797 return -1; 798 } 799 if (strcasecmp(*arg->argv, "sync") == 0) { 800 Physical_SetSync(arg->cx->physical); 801 return 0; 802 } 803 end = NULL; 804 speed = strtol(*arg->argv, &end, 10); 805 if (*end) { 806 LogPrintf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", *arg->argv); 807 return -1; 808 } 809 if (Physical_SetSpeed(arg->cx->physical, speed)) 810 return 0; 811 LogPrintf(LogWARN, "%s: Invalid speed\n", *arg->argv); 812 } else 813 LogPrintf(LogWARN, "SetModemSpeed: No speed specified\n"); 814 815 return -1; 816 } 817 818 static int 819 SetStoppedTimeout(struct cmdargs const *arg) 820 { 821 struct link *l = &arg->cx->physical->link; 822 823 l->lcp.fsm.StoppedTimer.load = 0; 824 l->ccp.fsm.StoppedTimer.load = 0; 825 if (arg->argc <= 2) { 826 if (arg->argc > 0) { 827 l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[0]) * SECTICKS; 828 if (arg->argc > 1) 829 l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[1]) * SECTICKS; 830 } 831 return 0; 832 } 833 return -1; 834 } 835 836 #define ismask(x) \ 837 (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 838 839 static int 840 SetServer(struct cmdargs const *arg) 841 { 842 int res = -1; 843 844 if (arg->argc > 0 && arg->argc < 4) { 845 const char *port, *passwd, *mask; 846 847 /* What's what ? */ 848 port = arg->argv[0]; 849 if (arg->argc == 2) { 850 passwd = arg->argv[1]; 851 mask = NULL; 852 } else if (arg->argc == 3) { 853 passwd = arg->argv[1]; 854 mask = arg->argv[2]; 855 if (!ismask(mask)) 856 return -1; 857 } else if (strcasecmp(port, "none") == 0) { 858 if (ServerClose(arg->bundle)) 859 LogPrintf(LogPHASE, "Disabled server port.\n"); 860 return 0; 861 } else 862 return -1; 863 864 strncpy(server.passwd, passwd, sizeof server.passwd - 1); 865 server.passwd[sizeof server.passwd - 1] = '\0'; 866 867 if (*port == '/') { 868 mode_t imask; 869 870 if (mask != NULL) { 871 unsigned m; 872 873 if (sscanf(mask, "%o", &m) == 1) 874 imask = m; 875 else 876 return -1; 877 } else 878 imask = (mode_t)-1; 879 res = ServerLocalOpen(arg->bundle, port, imask); 880 } else { 881 int iport; 882 883 if (mask != NULL) 884 return -1; 885 886 if (strspn(port, "0123456789") != strlen(port)) { 887 struct servent *s; 888 889 if ((s = getservbyname(port, "tcp")) == NULL) { 890 iport = 0; 891 LogPrintf(LogWARN, "%s: Invalid port or service\n", port); 892 } else 893 iport = ntohs(s->s_port); 894 } else 895 iport = atoi(port); 896 res = iport ? ServerTcpOpen(arg->bundle, iport) : -1; 897 } 898 } 899 900 return res; 901 } 902 903 static int 904 SetModemParity(struct cmdargs const *arg) 905 { 906 return arg->argc > 0 ? modem_SetParity(arg->cx->physical, *arg->argv) : -1; 907 } 908 909 static int 910 SetEscape(struct cmdargs const *arg) 911 { 912 int code; 913 int argc = arg->argc; 914 char const *const *argv = arg->argv; 915 916 for (code = 0; code < 33; code++) 917 arg->cx->physical->async.cfg.EscMap[code] = 0; 918 919 while (argc-- > 0) { 920 sscanf(*argv++, "%x", &code); 921 code &= 0xff; 922 arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 923 arg->cx->physical->async.cfg.EscMap[32] = 1; 924 } 925 return 0; 926 } 927 928 static struct in_addr 929 GetIpAddr(const char *cp) 930 { 931 struct hostent *hp; 932 struct in_addr ipaddr; 933 934 if (inet_aton(cp, &ipaddr) == 0) { 935 hp = gethostbyname(cp); 936 if (hp && hp->h_addrtype == AF_INET) 937 memcpy(&ipaddr, hp->h_addr, hp->h_length); 938 else 939 ipaddr.s_addr = 0; 940 } 941 return (ipaddr); 942 } 943 944 static int 945 SetInterfaceAddr(struct cmdargs const *arg) 946 { 947 struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 948 const char *hisaddr; 949 950 hisaddr = NULL; 951 ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 952 ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 953 954 if (arg->argc > 4) 955 return -1; 956 957 ipcp->cfg.HaveTriggerAddress = 0; 958 ipcp->cfg.netmask.s_addr = INADDR_ANY; 959 iplist_reset(&ipcp->cfg.peer_list); 960 961 if (arg->argc > 0) { 962 if (!ParseAddr(ipcp, arg->argc, arg->argv, &ipcp->cfg.my_range.ipaddr, 963 &ipcp->cfg.my_range.mask, &ipcp->cfg.my_range.width)) 964 return 1; 965 if (arg->argc > 1) { 966 hisaddr = arg->argv[1]; 967 if (arg->argc > 2) { 968 ipcp->cfg.netmask = GetIpAddr(arg->argv[2]); 969 if (arg->argc > 3) { 970 ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[3]); 971 ipcp->cfg.HaveTriggerAddress = 1; 972 } 973 } 974 } 975 } 976 977 /* 978 * For backwards compatibility, 0.0.0.0 means any address. 979 */ 980 if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 981 ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 982 ipcp->cfg.my_range.width = 0; 983 } 984 ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 985 986 if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 987 ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 988 ipcp->cfg.peer_range.width = 0; 989 } 990 991 if (hisaddr && 992 !UseHisaddr(arg->bundle, hisaddr, arg->bundle->phys_type & PHYS_DEMAND)) 993 return 4; 994 995 return 0; 996 } 997 998 #ifndef NOMSEXT 999 1000 static void 1001 SetMSEXT(struct ipcp *ipcp, struct in_addr * pri_addr, 1002 struct in_addr * sec_addr, int argc, char const *const *argv) 1003 { 1004 int dummyint; 1005 struct in_addr dummyaddr; 1006 1007 pri_addr->s_addr = sec_addr->s_addr = 0L; 1008 1009 if (argc > 0) { 1010 ParseAddr(ipcp, argc, argv++, pri_addr, &dummyaddr, &dummyint); 1011 if (--argc > 0) 1012 ParseAddr(ipcp, argc, argv++, sec_addr, &dummyaddr, &dummyint); 1013 else 1014 sec_addr->s_addr = pri_addr->s_addr; 1015 } 1016 1017 /* 1018 * if the primary/secondary ns entries are 0.0.0.0 we should set them to 1019 * either the localhost's ip, or the values in /etc/resolv.conf ?? 1020 * 1021 * up to you if you want to implement this... 1022 */ 1023 1024 } 1025 1026 static int 1027 SetNS(struct cmdargs const *arg) 1028 { 1029 SetMSEXT(&arg->bundle->ncp.ipcp, &arg->bundle->ncp.ipcp.cfg.ns_entries[0], 1030 &arg->bundle->ncp.ipcp.cfg.ns_entries[1], arg->argc, arg->argv); 1031 return 0; 1032 } 1033 1034 static int 1035 SetNBNS(struct cmdargs const *arg) 1036 { 1037 SetMSEXT(&arg->bundle->ncp.ipcp, &arg->bundle->ncp.ipcp.cfg.nbns_entries[0], 1038 &arg->bundle->ncp.ipcp.cfg.nbns_entries[1], arg->argc, arg->argv); 1039 return 0; 1040 } 1041 1042 #endif /* MS_EXT */ 1043 1044 static int 1045 SetVariable(struct cmdargs const *arg) 1046 { 1047 u_long ulong_val; 1048 const char *argp; 1049 int param = (int)arg->cmd->args; 1050 struct datalink *cx = arg->cx; /* AUTH_CX uses this */ 1051 const char *err = NULL; 1052 struct link *l = ChooseLink(arg); /* AUTH_CX_OPT uses this */ 1053 1054 if (arg->argc > 0) 1055 argp = *arg->argv; 1056 else 1057 argp = ""; 1058 1059 if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 1060 LogPrintf(LogWARN, "set %s: No context (use the `link' command)\n", 1061 arg->cmd->name); 1062 return 1; 1063 } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 1064 LogPrintf(LogWARN, "set %s: Redundant context (%s) ignored\n", 1065 arg->cmd->name, cx->name); 1066 cx = NULL; 1067 } 1068 1069 switch (param) { 1070 case VAR_AUTHKEY: 1071 if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 1072 strncpy(arg->bundle->cfg.auth.key, argp, 1073 sizeof arg->bundle->cfg.auth.key - 1); 1074 arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 1075 } else { 1076 err = "set authkey: Only available at phase DEAD\n"; 1077 LogPrintf(LogWARN, err); 1078 } 1079 break; 1080 case VAR_AUTHNAME: 1081 if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 1082 strncpy(arg->bundle->cfg.auth.name, argp, 1083 sizeof arg->bundle->cfg.auth.name - 1); 1084 arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 1085 } else { 1086 err = "set authname: Only available at phase DEAD\n"; 1087 LogPrintf(LogWARN, err); 1088 } 1089 break; 1090 case VAR_DIAL: 1091 strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 1092 cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 1093 break; 1094 case VAR_LOGIN: 1095 strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 1096 cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 1097 break; 1098 case VAR_WINSIZE: 1099 if (arg->argc > 0) { 1100 l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[0]); 1101 if (l->ccp.cfg.deflate.out.winsize < 8 || 1102 l->ccp.cfg.deflate.out.winsize > 15) { 1103 LogPrintf(LogWARN, "%d: Invalid outgoing window size\n", 1104 l->ccp.cfg.deflate.out.winsize); 1105 l->ccp.cfg.deflate.out.winsize = 15; 1106 } 1107 if (arg->argc > 1) { 1108 l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[1]); 1109 if (l->ccp.cfg.deflate.in.winsize < 8 || 1110 l->ccp.cfg.deflate.in.winsize > 15) { 1111 LogPrintf(LogWARN, "%d: Invalid incoming window size\n", 1112 l->ccp.cfg.deflate.in.winsize); 1113 l->ccp.cfg.deflate.in.winsize = 15; 1114 } 1115 } else 1116 l->ccp.cfg.deflate.in.winsize = 0; 1117 } else { 1118 err = "No window size specified\n"; 1119 LogPrintf(LogWARN, err); 1120 } 1121 break; 1122 case VAR_DEVICE: 1123 Physical_SetDeviceList(cx->physical, argp); 1124 break; 1125 case VAR_ACCMAP: 1126 if (arg->argc > 0) { 1127 sscanf(argp, "%lx", &ulong_val); 1128 cx->physical->link.lcp.cfg.accmap = ulong_val; 1129 } else { 1130 err = "No accmap specified\n"; 1131 LogPrintf(LogWARN, err); 1132 } 1133 break; 1134 case VAR_MRU: 1135 ulong_val = atol(argp); 1136 if (ulong_val < MIN_MRU) 1137 err = "Given MRU value (%lu) is too small.\n"; 1138 else if (ulong_val > MAX_MRU) 1139 err = "Given MRU value (%lu) is too big.\n"; 1140 else 1141 l->lcp.cfg.mru = ulong_val; 1142 if (err) 1143 LogPrintf(LogWARN, err, ulong_val); 1144 break; 1145 case VAR_MTU: 1146 ulong_val = atol(argp); 1147 if (ulong_val == 0) 1148 l->lcp.cfg.mtu = 0; 1149 else if (ulong_val < MIN_MTU) 1150 err = "Given MTU value (%lu) is too small.\n"; 1151 else if (ulong_val > MAX_MTU) 1152 err = "Given MTU value (%lu) is too big.\n"; 1153 else 1154 l->lcp.cfg.mtu = ulong_val; 1155 if (err) 1156 LogPrintf(LogWARN, err, ulong_val); 1157 break; 1158 case VAR_OPENMODE: 1159 if (strcasecmp(argp, "active") == 0) 1160 cx->physical->link.lcp.cfg.openmode = arg->argc > 1 ? 1161 atoi(arg->argv[1]) : 1; 1162 else if (strcasecmp(argp, "passive") == 0) 1163 cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 1164 else { 1165 err = "%s: Invalid openmode\n"; 1166 LogPrintf(LogWARN, err, argp); 1167 } 1168 break; 1169 case VAR_PHONE: 1170 strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 1171 cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 1172 break; 1173 case VAR_HANGUP: 1174 strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 1175 cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 1176 break; 1177 case VAR_IDLETIMEOUT: 1178 if (arg->argc > 1) 1179 err = "Too many idle timeout values\n"; 1180 else if (arg->argc == 1) 1181 bundle_SetIdleTimer(arg->bundle, atoi(argp)); 1182 if (err) 1183 LogPrintf(LogWARN, err); 1184 break; 1185 case VAR_LQRPERIOD: 1186 ulong_val = atol(argp); 1187 if (ulong_val <= 0) { 1188 err = "%s: Invalid lqr period\n"; 1189 LogPrintf(LogWARN, err, argp); 1190 } else 1191 l->lcp.cfg.lqrperiod = ulong_val; 1192 break; 1193 case VAR_LCPRETRY: 1194 ulong_val = atol(argp); 1195 if (ulong_val <= 0) { 1196 err = "%s: Invalid LCP FSM retry period\n"; 1197 LogPrintf(LogWARN, err, argp); 1198 } else 1199 cx->physical->link.lcp.cfg.fsmretry = ulong_val; 1200 break; 1201 case VAR_CHAPRETRY: 1202 ulong_val = atol(argp); 1203 if (ulong_val <= 0) { 1204 err = "%s: Invalid CHAP retry period\n"; 1205 LogPrintf(LogWARN, err, argp); 1206 } else 1207 cx->chap.auth.cfg.fsmretry = ulong_val; 1208 break; 1209 case VAR_PAPRETRY: 1210 ulong_val = atol(argp); 1211 if (ulong_val <= 0) { 1212 err = "%s: Invalid PAP retry period\n"; 1213 LogPrintf(LogWARN, err, argp); 1214 } else 1215 cx->pap.cfg.fsmretry = ulong_val; 1216 break; 1217 case VAR_CCPRETRY: 1218 ulong_val = atol(argp); 1219 if (ulong_val <= 0) { 1220 err = "%s: Invalid CCP FSM retry period\n"; 1221 LogPrintf(LogWARN, err, argp); 1222 } else 1223 l->ccp.cfg.fsmretry = ulong_val; 1224 break; 1225 case VAR_IPCPRETRY: 1226 ulong_val = atol(argp); 1227 if (ulong_val <= 0) { 1228 err = "%s: Invalid IPCP FSM retry period\n"; 1229 LogPrintf(LogWARN, err, argp); 1230 } else 1231 arg->bundle->ncp.ipcp.cfg.fsmretry = ulong_val; 1232 break; 1233 } 1234 1235 return err ? 1 : 0; 1236 } 1237 1238 static int 1239 SetCtsRts(struct cmdargs const *arg) 1240 { 1241 if (arg->argc == 1) { 1242 if (strcmp(*arg->argv, "on") == 0) 1243 Physical_SetRtsCts(arg->cx->physical, 1); 1244 else if (strcmp(*arg->argv, "off") == 0) 1245 Physical_SetRtsCts(arg->cx->physical, 0); 1246 else 1247 return -1; 1248 return 0; 1249 } 1250 return -1; 1251 } 1252 1253 static struct cmdtab const SetCommands[] = { 1254 {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1255 "Set accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 1256 {"authkey", "key", SetVariable, LOCAL_AUTH, 1257 "Set authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 1258 {"authname", NULL, SetVariable, LOCAL_AUTH, 1259 "Set authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 1260 {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 1261 "Set FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 1262 {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1263 "Set CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 1264 {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 1265 "Use hardware flow control", "set ctsrts [on|off]"}, 1266 {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 1267 "Set deflate window sizes", "set deflate out-winsize in-winsize", 1268 (const void *) VAR_WINSIZE}, 1269 {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 1270 "Set modem device name", "set device|line device-name[,device-name]", 1271 (const void *) VAR_DEVICE}, 1272 {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1273 "Set dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 1274 {"encrypt", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1275 "Select CHAP encryption type", "set encrypt MSChap|MD5", 1276 (const void *)VAR_ENC}, 1277 {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 1278 "Set escape characters", "set escape hex-digit ..."}, 1279 {"filter", NULL, SetFilter, LOCAL_AUTH, 1280 "Set packet filters", "set filter in|out|dial|alive ..."}, 1281 {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1282 "Set hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 1283 {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "Set destination address", 1284 "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 1285 {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 1286 "Set FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 1287 {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1288 "Set FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 1289 {"log", NULL, log_SetLevel, LOCAL_AUTH, 1290 "Set log level", "set log [local] [+|-]value..."}, 1291 {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1292 "Set login script", "set login chat-script", (const void *) VAR_LOGIN}, 1293 {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 1294 "Set LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 1295 {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 1296 "Set MRU value", "set mru value", (const void *)VAR_MRU}, 1297 {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 1298 "Set MTU value", "set mtu value", (const void *)VAR_MTU}, 1299 #ifndef NOMSEXT 1300 {"nbns", NULL, SetNBNS, LOCAL_AUTH, 1301 "Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"}, 1302 {"ns", NULL, SetNS, LOCAL_AUTH, 1303 "Set NameServer", "set ns pri-addr [sec-addr]"}, 1304 #endif 1305 {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Set open mode", 1306 "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 1307 {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 1308 "Set PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 1309 {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 1310 "Set modem parity", "set parity [odd|even|none]"}, 1311 {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Set telephone number(s)", 1312 "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 1313 {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 1314 "Set Reconnect timeout", "set reconnect value ntries"}, 1315 {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 1316 "Set Redial timeout", "set redial value|random[.value|random] [attempts]"}, 1317 {"server", "socket", SetServer, LOCAL_AUTH, 1318 "Set server port", "set server|socket TcpPort|LocalName|none [mask]"}, 1319 {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 1320 "Set modem speed", "set speed value"}, 1321 {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 1322 "Set STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 1323 {"timeout", NULL, SetVariable, LOCAL_AUTH, "Set Idle timeout", 1324 "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 1325 {"vj", NULL, SetInitVJ, LOCAL_AUTH, 1326 "Set vj values", "set vj slots|slotcomp [value]"}, 1327 {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 1328 "Set datalink weighting", "set weight n"}, 1329 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 1330 "Display this message", "set help|? [command]", SetCommands}, 1331 {NULL, NULL, NULL}, 1332 }; 1333 1334 static int 1335 SetCommand(struct cmdargs const *arg) 1336 { 1337 if (arg->argc > 0) 1338 FindExec(arg->bundle, SetCommands, arg->argc, arg->argv, "set ", 1339 arg->prompt, arg->cx); 1340 else if (arg->prompt) 1341 prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 1342 " syntax help.\n"); 1343 else 1344 LogPrintf(LogWARN, "set command must have arguments\n"); 1345 1346 return 0; 1347 } 1348 1349 1350 static int 1351 AddCommand(struct cmdargs const *arg) 1352 { 1353 struct in_addr dest, gateway, netmask; 1354 int gw; 1355 1356 if (arg->argc != 3 && arg->argc != 2) 1357 return -1; 1358 1359 if (arg->argc == 2) 1360 if (strcasecmp(arg->argv[0], "default")) 1361 return -1; 1362 else { 1363 dest.s_addr = netmask.s_addr = INADDR_ANY; 1364 gw = 1; 1365 } 1366 else { 1367 if (strcasecmp(arg->argv[0], "MYADDR") == 0) 1368 dest = arg->bundle->ncp.ipcp.my_ip; 1369 else if (strcasecmp(arg->argv[0], "HISADDR") == 0) 1370 dest = arg->bundle->ncp.ipcp.peer_ip; 1371 else 1372 dest = GetIpAddr(arg->argv[0]); 1373 netmask = GetIpAddr(arg->argv[1]); 1374 gw = 2; 1375 } 1376 if (strcasecmp(arg->argv[gw], "HISADDR") == 0) 1377 gateway = arg->bundle->ncp.ipcp.peer_ip; 1378 else if (strcasecmp(arg->argv[gw], "INTERFACE") == 0) 1379 gateway.s_addr = INADDR_ANY; 1380 else 1381 gateway = GetIpAddr(arg->argv[gw]); 1382 bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 1383 arg->cmd->args ? 1 : 0); 1384 return 0; 1385 } 1386 1387 static int 1388 DeleteCommand(struct cmdargs const *arg) 1389 { 1390 struct in_addr dest, none; 1391 1392 if (arg->argc == 1) 1393 if(strcasecmp(arg->argv[0], "all") == 0) 1394 DeleteIfRoutes(arg->bundle, 0); 1395 else { 1396 if (strcasecmp(arg->argv[0], "MYADDR") == 0) 1397 dest = arg->bundle->ncp.ipcp.my_ip; 1398 else if (strcasecmp(arg->argv[0], "default") == 0) 1399 dest.s_addr = INADDR_ANY; 1400 else 1401 dest = GetIpAddr(arg->argv[0]); 1402 none.s_addr = INADDR_ANY; 1403 bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 1404 arg->cmd->args ? 1 : 0); 1405 } 1406 else 1407 return -1; 1408 1409 return 0; 1410 } 1411 1412 #ifndef NOALIAS 1413 static struct cmdtab const AliasCommands[] = 1414 { 1415 {"addr", NULL, AliasRedirectAddr, LOCAL_AUTH, 1416 "static address translation", "alias addr [addr_local addr_alias]"}, 1417 {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 1418 "stop incoming connections", "alias deny_incoming [yes|no]", 1419 (const void *) PKT_ALIAS_DENY_INCOMING}, 1420 {"enable", NULL, AliasEnable, LOCAL_AUTH, 1421 "enable IP aliasing", "alias enable [yes|no]"}, 1422 {"log", NULL, AliasOption, LOCAL_AUTH, 1423 "log aliasing link creation", "alias log [yes|no]", 1424 (const void *) PKT_ALIAS_LOG}, 1425 {"port", NULL, AliasRedirectPort, LOCAL_AUTH, 1426 "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 1427 {"same_ports", NULL, AliasOption, LOCAL_AUTH, 1428 "try to leave port numbers unchanged", "alias same_ports [yes|no]", 1429 (const void *) PKT_ALIAS_SAME_PORTS}, 1430 {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 1431 "alias unregistered (private) IP address space only", 1432 "alias unregistered_only [yes|no]", 1433 (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 1434 {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 1435 "allocate host sockets", "alias use_sockets [yes|no]", 1436 (const void *) PKT_ALIAS_USE_SOCKETS}, 1437 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 1438 "Display this message", "alias help|? [command]", AliasCommands}, 1439 {NULL, NULL, NULL}, 1440 }; 1441 1442 1443 static int 1444 AliasCommand(struct cmdargs const *arg) 1445 { 1446 if (arg->argc > 0) 1447 FindExec(arg->bundle, AliasCommands, arg->argc, arg->argv, "alias ", 1448 arg->prompt, arg->cx); 1449 else if (arg->prompt) 1450 prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 1451 " <option>' for syntax help.\n"); 1452 else 1453 LogPrintf(LogWARN, "alias command must have arguments\n"); 1454 1455 return 0; 1456 } 1457 1458 static int 1459 AliasEnable(struct cmdargs const *arg) 1460 { 1461 if (arg->argc == 1) 1462 if (strcasecmp(arg->argv[0], "yes") == 0) { 1463 if (loadAliasHandlers() == 0) 1464 return 0; 1465 LogPrintf(LogWARN, "Cannot load alias library\n"); 1466 return 1; 1467 } else if (strcasecmp(arg->argv[0], "no") == 0) { 1468 unloadAliasHandlers(); 1469 return 0; 1470 } 1471 return -1; 1472 } 1473 1474 1475 static int 1476 AliasOption(struct cmdargs const *arg) 1477 { 1478 unsigned param = (unsigned)arg->cmd->args; 1479 if (arg->argc == 1) 1480 if (strcasecmp(arg->argv[0], "yes") == 0) { 1481 if (AliasEnabled()) { 1482 (*PacketAlias.SetMode)(param, param); 1483 return 0; 1484 } 1485 LogPrintf(LogWARN, "alias not enabled\n"); 1486 } else if (strcmp(arg->argv[0], "no") == 0) { 1487 if (AliasEnabled()) { 1488 (*PacketAlias.SetMode)(0, param); 1489 return 0; 1490 } 1491 LogPrintf(LogWARN, "alias not enabled\n"); 1492 } 1493 return -1; 1494 } 1495 #endif /* #ifndef NOALIAS */ 1496 1497 static struct cmdtab const AllowCommands[] = { 1498 {"modes", "mode", AllowModes, LOCAL_AUTH, 1499 "Only allow certain ppp modes", "allow modes mode..."}, 1500 {"users", "user", AllowUsers, LOCAL_AUTH, 1501 "Allow users access to ppp", "allow users logname..."}, 1502 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 1503 "Display this message", "allow help|? [command]", AllowCommands}, 1504 {NULL, NULL, NULL}, 1505 }; 1506 1507 static int 1508 AllowCommand(struct cmdargs const *arg) 1509 { 1510 /* arg->bundle may be NULL (see ValidSystem()) ! */ 1511 if (arg->argc > 0) 1512 FindExec(arg->bundle, AllowCommands, arg->argc, arg->argv, "allow ", 1513 arg->prompt, arg->cx); 1514 else if (arg->prompt) 1515 prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 1516 " for syntax help.\n"); 1517 else 1518 LogPrintf(LogWARN, "allow command must have arguments\n"); 1519 1520 return 0; 1521 } 1522 1523 static int 1524 LinkCommand(struct cmdargs const *arg) 1525 { 1526 if (arg->argc > 1) { 1527 struct datalink *cx = bundle2datalink(arg->bundle, arg->argv[0]); 1528 if (cx) 1529 FindExec(arg->bundle, Commands, arg->argc - 1, arg->argv + 1, "", 1530 arg->prompt, cx); 1531 else { 1532 LogPrintf(LogWARN, "link: %s: Invalid link name\n", arg->argv[0]); 1533 return 1; 1534 } 1535 } else { 1536 LogPrintf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 1537 return 2; 1538 } 1539 1540 return 0; 1541 } 1542 1543 struct link * 1544 ChooseLink(struct cmdargs const *arg) 1545 { 1546 if (arg->cx) 1547 return &arg->cx->physical->link; 1548 else if (arg->bundle->ncp.mp.active) 1549 return &arg->bundle->ncp.mp.link; 1550 else { 1551 struct datalink *dl = bundle2datalink(arg->bundle, NULL); 1552 return dl ? &dl->physical->link : NULL; 1553 } 1554 } 1555