1 /*- 2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 4 * Internet Initiative Japan, Inc (IIJ) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <netinet/in_systm.h> 33 #include <netinet/in.h> 34 #include <netinet/ip.h> 35 #include <arpa/inet.h> 36 #include <sys/socket.h> 37 #include <net/route.h> 38 #include <netdb.h> 39 #include <sys/un.h> 40 41 #include <ctype.h> 42 #include <errno.h> 43 #include <fcntl.h> 44 #include <paths.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <sys/wait.h> 49 #include <termios.h> 50 #include <unistd.h> 51 52 #ifndef NONAT 53 #ifdef LOCALNAT 54 #include "alias.h" 55 #else 56 #include <alias.h> 57 #endif 58 #endif 59 60 #include "layer.h" 61 #include "defs.h" 62 #include "command.h" 63 #include "mbuf.h" 64 #include "log.h" 65 #include "timer.h" 66 #include "fsm.h" 67 #include "iplist.h" 68 #include "throughput.h" 69 #include "slcompress.h" 70 #include "lqr.h" 71 #include "hdlc.h" 72 #include "lcp.h" 73 #include "ipcp.h" 74 #ifndef NONAT 75 #include "nat_cmd.h" 76 #endif 77 #include "systems.h" 78 #include "filter.h" 79 #include "descriptor.h" 80 #include "main.h" 81 #include "route.h" 82 #include "ccp.h" 83 #include "auth.h" 84 #include "async.h" 85 #include "link.h" 86 #include "physical.h" 87 #include "mp.h" 88 #ifndef NORADIUS 89 #include "radius.h" 90 #endif 91 #include "bundle.h" 92 #include "server.h" 93 #include "prompt.h" 94 #include "chat.h" 95 #include "chap.h" 96 #include "cbcp.h" 97 #include "datalink.h" 98 #include "iface.h" 99 #include "id.h" 100 101 /* ``set'' values */ 102 #define VAR_AUTHKEY 0 103 #define VAR_DIAL 1 104 #define VAR_LOGIN 2 105 #define VAR_AUTHNAME 3 106 #define VAR_AUTOLOAD 4 107 #define VAR_WINSIZE 5 108 #define VAR_DEVICE 6 109 #define VAR_ACCMAP 7 110 #define VAR_MRRU 8 111 #define VAR_MRU 9 112 #define VAR_MTU 10 113 #define VAR_OPENMODE 11 114 #define VAR_PHONE 12 115 #define VAR_HANGUP 13 116 #define VAR_IDLETIMEOUT 14 117 #define VAR_LQRPERIOD 15 118 #define VAR_LCPRETRY 16 119 #define VAR_CHAPRETRY 17 120 #define VAR_PAPRETRY 18 121 #define VAR_CCPRETRY 19 122 #define VAR_IPCPRETRY 20 123 #define VAR_DNS 21 124 #define VAR_NBNS 22 125 #define VAR_MODE 23 126 #define VAR_CALLBACK 24 127 #define VAR_CBCP 25 128 #define VAR_CHOKED 26 129 #define VAR_SENDPIPE 27 130 #define VAR_RECVPIPE 28 131 #define VAR_RADIUS 29 132 #define VAR_CD 30 133 #define VAR_PARITY 31 134 #define VAR_CRTSCTS 32 135 #define VAR_URGENTPORTS 33 136 #define VAR_LOGOUT 34 137 #define VAR_IFQUEUE 35 138 #define VAR_MPPE 36 139 140 /* ``accept|deny|disable|enable'' masks */ 141 #define NEG_HISMASK (1) 142 #define NEG_MYMASK (2) 143 144 /* ``accept|deny|disable|enable'' values */ 145 #define NEG_ACFCOMP 40 146 #define NEG_CHAP05 41 147 #define NEG_CHAP80 42 148 #define NEG_CHAP80LM 43 149 #define NEG_DEFLATE 44 150 #define NEG_DNS 45 151 #define NEG_ENDDISC 46 152 #define NEG_LQR 47 153 #define NEG_PAP 48 154 #define NEG_PPPDDEFLATE 49 155 #define NEG_PRED1 50 156 #define NEG_PROTOCOMP 51 157 #define NEG_SHORTSEQ 52 158 #define NEG_VJCOMP 53 159 #define NEG_MPPE 54 160 #define NEG_CHAP81 55 161 162 const char Version[] = "2.3.2"; 163 164 static int ShowCommand(struct cmdargs const *); 165 static int TerminalCommand(struct cmdargs const *); 166 static int QuitCommand(struct cmdargs const *); 167 static int OpenCommand(struct cmdargs const *); 168 static int CloseCommand(struct cmdargs const *); 169 static int DownCommand(struct cmdargs const *); 170 static int SetCommand(struct cmdargs const *); 171 static int LinkCommand(struct cmdargs const *); 172 static int AddCommand(struct cmdargs const *); 173 static int DeleteCommand(struct cmdargs const *); 174 static int NegotiateCommand(struct cmdargs const *); 175 static int ClearCommand(struct cmdargs const *); 176 static int RunListCommand(struct cmdargs const *); 177 static int IfaceAddCommand(struct cmdargs const *); 178 static int IfaceDeleteCommand(struct cmdargs const *); 179 static int IfaceClearCommand(struct cmdargs const *); 180 static int SetProcTitle(struct cmdargs const *); 181 #ifndef NONAT 182 static int NatEnable(struct cmdargs const *); 183 static int NatOption(struct cmdargs const *); 184 #endif 185 186 static const char * 187 showcx(struct cmdtab const *cmd) 188 { 189 if (cmd->lauth & LOCAL_CX) 190 return "(c)"; 191 else if (cmd->lauth & LOCAL_CX_OPT) 192 return "(o)"; 193 194 return ""; 195 } 196 197 static int 198 HelpCommand(struct cmdargs const *arg) 199 { 200 struct cmdtab const *cmd; 201 int n, cmax, dmax, cols, cxlen; 202 const char *cx; 203 204 if (!arg->prompt) { 205 log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 206 return 0; 207 } 208 209 if (arg->argc > arg->argn) { 210 for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 211 if ((cmd->lauth & arg->prompt->auth) && 212 ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 213 (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 214 prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 215 return 0; 216 } 217 return -1; 218 } 219 220 cmax = dmax = 0; 221 for (cmd = arg->cmdtab; cmd->func; cmd++) 222 if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 223 if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 224 cmax = n; 225 if ((n = strlen(cmd->helpmes)) > dmax) 226 dmax = n; 227 } 228 229 cols = 80 / (dmax + cmax + 3); 230 n = 0; 231 prompt_Printf(arg->prompt, "(o) = Optional context," 232 " (c) = Context required\n"); 233 for (cmd = arg->cmdtab; cmd->func; cmd++) 234 if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 235 cx = showcx(cmd); 236 cxlen = cmax - strlen(cmd->name); 237 if (n % cols != 0) 238 prompt_Printf(arg->prompt, " "); 239 prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 240 cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 241 if (++n % cols == 0) 242 prompt_Printf(arg->prompt, "\n"); 243 } 244 if (n % cols != 0) 245 prompt_Printf(arg->prompt, "\n"); 246 247 return 0; 248 } 249 250 static int 251 IdentCommand(struct cmdargs const *arg) 252 { 253 int f, pos; 254 255 *arg->cx->physical->link.lcp.cfg.ident = '\0'; 256 257 for (pos = 0, f = arg->argn; f < arg->argc; f++) 258 pos += snprintf(arg->cx->physical->link.lcp.cfg.ident + pos, 259 sizeof arg->cx->physical->link.lcp.cfg.ident - pos, "%s%s", 260 f == arg->argn ? "" : " ", arg->argv[f]); 261 262 return 0; 263 } 264 265 static int 266 SendIdentification(struct cmdargs const *arg) 267 { 268 if (arg->cx->state < DATALINK_LCP) { 269 log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 270 return 2; 271 } 272 return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 273 } 274 275 static int 276 CloneCommand(struct cmdargs const *arg) 277 { 278 char namelist[LINE_LEN]; 279 char *name; 280 int f; 281 282 if (arg->argc == arg->argn) 283 return -1; 284 285 namelist[sizeof namelist - 1] = '\0'; 286 for (f = arg->argn; f < arg->argc; f++) { 287 strncpy(namelist, arg->argv[f], sizeof namelist - 1); 288 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 289 bundle_DatalinkClone(arg->bundle, arg->cx, name); 290 } 291 292 return 0; 293 } 294 295 static int 296 RemoveCommand(struct cmdargs const *arg) 297 { 298 if (arg->argc != arg->argn) 299 return -1; 300 301 if (arg->cx->state != DATALINK_CLOSED) { 302 log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 303 return 2; 304 } 305 306 bundle_DatalinkRemove(arg->bundle, arg->cx); 307 return 0; 308 } 309 310 static int 311 RenameCommand(struct cmdargs const *arg) 312 { 313 if (arg->argc != arg->argn + 1) 314 return -1; 315 316 if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 317 return 0; 318 319 log_Printf(LogWARN, "%s -> %s: target name already exists\n", 320 arg->cx->name, arg->argv[arg->argn]); 321 return 1; 322 } 323 324 int 325 LoadCommand(struct cmdargs const *arg) 326 { 327 const char *err; 328 int n, mode; 329 330 mode = arg->bundle->phys_type.all; 331 332 if (arg->argn < arg->argc) { 333 for (n = arg->argn; n < arg->argc; n++) 334 if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 335 log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 336 return 1; 337 } 338 339 for (n = arg->argn; n < arg->argc; n++) { 340 bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 341 system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 342 } 343 bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 344 } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 345 log_Printf(LogWARN, "default: %s\n", err); 346 return 1; 347 } else { 348 bundle_SetLabel(arg->bundle, "default"); 349 system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 350 bundle_SetLabel(arg->bundle, "default"); 351 } 352 353 return 0; 354 } 355 356 int 357 SaveCommand(struct cmdargs const *arg) 358 { 359 log_Printf(LogWARN, "save command is not implemented (yet).\n"); 360 return 1; 361 } 362 363 static int 364 DialCommand(struct cmdargs const *arg) 365 { 366 int res; 367 368 if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 369 || (!arg->cx && 370 (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 371 log_Printf(LogWARN, "Manual dial is only available for auto and" 372 " interactive links\n"); 373 return 1; 374 } 375 376 if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 377 return res; 378 379 bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 380 381 return 0; 382 } 383 384 #define isinword(ch) (isalnum(ch) || (ch) == '_') 385 386 static char * 387 strstrword(char *big, const char *little) 388 { 389 /* Get the first occurance of the word ``little'' in ``big'' */ 390 char *pos; 391 int len; 392 393 pos = big; 394 len = strlen(little); 395 396 while ((pos = strstr(pos, little)) != NULL) 397 if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 398 pos++; 399 else if (pos != big && pos[-1] == '\\') 400 memmove(pos - 1, pos, strlen(pos) + 1); 401 else 402 break; 403 404 return pos; 405 } 406 407 static char * 408 subst(char *tgt, const char *oldstr, const char *newstr) 409 { 410 /* tgt is a malloc()d area... realloc() as necessary */ 411 char *word, *ntgt; 412 int ltgt, loldstr, lnewstr, pos; 413 414 if ((word = strstrword(tgt, oldstr)) == NULL) 415 return tgt; 416 417 ltgt = strlen(tgt) + 1; 418 loldstr = strlen(oldstr); 419 lnewstr = strlen(newstr); 420 do { 421 pos = word - tgt; 422 if (loldstr > lnewstr) 423 bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 424 if (loldstr != lnewstr) { 425 ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 426 if (ntgt == NULL) 427 break; /* Oh wonderful ! */ 428 word = ntgt + pos; 429 tgt = ntgt; 430 } 431 if (lnewstr > loldstr) 432 bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 433 bcopy(newstr, word, lnewstr); 434 } while ((word = strstrword(word, oldstr))); 435 436 return tgt; 437 } 438 439 void 440 command_Expand(char **nargv, int argc, char const *const *oargv, 441 struct bundle *bundle, int inc0, pid_t pid) 442 { 443 int arg; 444 char pidstr[12]; 445 446 if (inc0) 447 arg = 0; /* Start at arg 0 */ 448 else { 449 nargv[0] = strdup(oargv[0]); 450 arg = 1; 451 } 452 snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 453 for (; arg < argc; arg++) { 454 nargv[arg] = strdup(oargv[arg]); 455 nargv[arg] = subst(nargv[arg], "HISADDR", 456 inet_ntoa(bundle->ncp.ipcp.peer_ip)); 457 nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 458 nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 459 nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 460 nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 461 nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 462 mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 463 bundle->ncp.mp.peer.enddisc.address, 464 bundle->ncp.mp.peer.enddisc.len)); 465 nargv[arg] = subst(nargv[arg], "ENDDISC", 466 mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 467 bundle->ncp.mp.cfg.enddisc.address, 468 bundle->ncp.mp.cfg.enddisc.len)); 469 nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 470 nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 471 nargv[arg] = subst(nargv[arg], "DNS0", 472 inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); 473 nargv[arg] = subst(nargv[arg], "DNS1", 474 inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); 475 nargv[arg] = subst(nargv[arg], "VERSION", Version); 476 nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 477 } 478 nargv[arg] = NULL; 479 } 480 481 static int 482 ShellCommand(struct cmdargs const *arg, int bg) 483 { 484 const char *shell; 485 pid_t shpid, pid; 486 487 #ifdef SHELL_ONLY_INTERACTIVELY 488 /* we're only allowed to shell when we run ppp interactively */ 489 if (arg->prompt && arg->prompt->owner) { 490 log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 491 return 1; 492 } 493 #endif 494 495 if (arg->argc == arg->argn) { 496 if (!arg->prompt) { 497 log_Printf(LogWARN, "Can't start an interactive shell from" 498 " a config file\n"); 499 return 1; 500 } else if (arg->prompt->owner) { 501 log_Printf(LogWARN, "Can't start an interactive shell from" 502 " a socket connection\n"); 503 return 1; 504 } else if (bg) { 505 log_Printf(LogWARN, "Can only start an interactive shell in" 506 " the foreground mode\n"); 507 return 1; 508 } 509 } 510 511 pid = getpid(); 512 if ((shpid = fork()) == 0) { 513 int i, fd; 514 515 if ((shell = getenv("SHELL")) == 0) 516 shell = _PATH_BSHELL; 517 518 timer_TermService(); 519 520 if (arg->prompt) 521 fd = arg->prompt->fd_out; 522 else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 523 log_Printf(LogALERT, "Failed to open %s: %s\n", 524 _PATH_DEVNULL, strerror(errno)); 525 exit(1); 526 } 527 dup2(fd, STDIN_FILENO); 528 dup2(fd, STDOUT_FILENO); 529 dup2(fd, STDERR_FILENO); 530 for (i = getdtablesize(); i > STDERR_FILENO; i--) 531 fcntl(i, F_SETFD, 1); 532 533 #ifndef NOSUID 534 setuid(ID0realuid()); 535 #endif 536 if (arg->argc > arg->argn) { 537 /* substitute pseudo args */ 538 char *argv[MAXARGS]; 539 int argc = arg->argc - arg->argn; 540 541 if (argc >= sizeof argv / sizeof argv[0]) { 542 argc = sizeof argv / sizeof argv[0] - 1; 543 log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 544 } 545 command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 546 if (bg) { 547 pid_t p; 548 549 p = getpid(); 550 if (daemon(1, 1) == -1) { 551 log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 552 exit(1); 553 } 554 } else if (arg->prompt) 555 printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 556 execvp(argv[0], argv); 557 } else { 558 if (arg->prompt) 559 printf("ppp: Pausing until %s finishes\n", shell); 560 prompt_TtyOldMode(arg->prompt); 561 execl(shell, shell, (char *)NULL); 562 } 563 564 log_Printf(LogWARN, "exec() of %s failed: %s\n", 565 arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 566 strerror(errno)); 567 _exit(255); 568 } 569 570 if (shpid == (pid_t) - 1) 571 log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 572 else { 573 int status; 574 waitpid(shpid, &status, 0); 575 } 576 577 if (arg->prompt && !arg->prompt->owner) 578 prompt_TtyCommandMode(arg->prompt); 579 580 return 0; 581 } 582 583 static int 584 BgShellCommand(struct cmdargs const *arg) 585 { 586 if (arg->argc == arg->argn) 587 return -1; 588 return ShellCommand(arg, 1); 589 } 590 591 static int 592 FgShellCommand(struct cmdargs const *arg) 593 { 594 return ShellCommand(arg, 0); 595 } 596 597 static int 598 ResolvCommand(struct cmdargs const *arg) 599 { 600 if (arg->argc == arg->argn + 1) { 601 if (!strcasecmp(arg->argv[arg->argn], "reload")) 602 ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 603 else if (!strcasecmp(arg->argv[arg->argn], "restore")) 604 ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 605 else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 606 ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 607 else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 608 arg->bundle->ncp.ipcp.ns.writable = 0; 609 else if (!strcasecmp(arg->argv[arg->argn], "writable")) 610 arg->bundle->ncp.ipcp.ns.writable = 1; 611 else 612 return -1; 613 614 return 0; 615 } 616 617 return -1; 618 } 619 620 #ifndef NONAT 621 static struct cmdtab const NatCommands[] = 622 { 623 {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 624 "static address translation", "nat addr [addr_local addr_alias]"}, 625 {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 626 "stop incoming connections", "nat deny_incoming yes|no", 627 (const void *) PKT_ALIAS_DENY_INCOMING}, 628 {"enable", NULL, NatEnable, LOCAL_AUTH, 629 "enable NAT", "nat enable yes|no"}, 630 {"log", NULL, NatOption, LOCAL_AUTH, 631 "log NAT link creation", "nat log yes|no", 632 (const void *) PKT_ALIAS_LOG}, 633 {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 634 "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 635 {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 636 "nat proto proto localIP [publicIP [remoteIP]]"}, 637 {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 638 "proxy control", "nat proxy server host[:port] ..."}, 639 #ifndef NO_FW_PUNCH 640 {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 641 "firewall control", "nat punch_fw [base count]"}, 642 #endif 643 {"same_ports", NULL, NatOption, LOCAL_AUTH, 644 "try to leave port numbers unchanged", "nat same_ports yes|no", 645 (const void *) PKT_ALIAS_SAME_PORTS}, 646 {"target", NULL, nat_SetTarget, LOCAL_AUTH, 647 "Default address for incoming connections", "nat target addr" }, 648 {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 649 "translate unregistered (private) IP address space only", 650 "nat unregistered_only yes|no", 651 (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 652 {"use_sockets", NULL, NatOption, LOCAL_AUTH, 653 "allocate host sockets", "nat use_sockets yes|no", 654 (const void *) PKT_ALIAS_USE_SOCKETS}, 655 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 656 "Display this message", "nat help|? [command]", NatCommands}, 657 {NULL, NULL, NULL}, 658 }; 659 #endif 660 661 static struct cmdtab const AllowCommands[] = { 662 {"modes", "mode", AllowModes, LOCAL_AUTH, 663 "Only allow certain ppp modes", "allow modes mode..."}, 664 {"users", "user", AllowUsers, LOCAL_AUTH, 665 "Only allow ppp access to certain users", "allow users logname..."}, 666 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 667 "Display this message", "allow help|? [command]", AllowCommands}, 668 {NULL, NULL, NULL}, 669 }; 670 671 static struct cmdtab const IfaceCommands[] = 672 { 673 {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 674 "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 675 {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 676 "Add or change an iface address", "iface add! addr[/bits| mask] peer", 677 (void *)1}, 678 {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 679 "Clear iface address(es)", "iface clear"}, 680 {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 681 "Delete iface address", "iface delete addr", NULL}, 682 {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 683 "Delete iface address", "iface delete addr", (void *)1}, 684 {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 685 "Delete iface address", "iface delete addr", (void *)1}, 686 {"show", NULL, iface_Show, LOCAL_AUTH, 687 "Show iface address(es)", "iface show"}, 688 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 689 "Display this message", "nat help|? [command]", IfaceCommands}, 690 {NULL, NULL, NULL}, 691 }; 692 693 static struct cmdtab const Commands[] = { 694 {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 695 "accept option request", "accept option .."}, 696 {"add", NULL, AddCommand, LOCAL_AUTH, 697 "add route", "add dest mask gateway", NULL}, 698 {NULL, "add!", AddCommand, LOCAL_AUTH, 699 "add or change route", "add! dest mask gateway", (void *)1}, 700 {"allow", "auth", RunListCommand, LOCAL_AUTH, 701 "Allow ppp access", "allow users|modes ....", AllowCommands}, 702 {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 703 "Run a background command", "[!]bg command"}, 704 {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 705 "Clear throughput statistics", 706 "clear ipcp|physical [current|overall|peak]..."}, 707 {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 708 "Clone a link", "clone newname..."}, 709 {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 710 "Close an FSM", "close [lcp|ccp]"}, 711 {"delete", NULL, DeleteCommand, LOCAL_AUTH, 712 "delete route", "delete dest", NULL}, 713 {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 714 "delete a route if it exists", "delete! dest", (void *)1}, 715 {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 716 "Deny option request", "deny option .."}, 717 {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 718 "Dial and login", "dial|call [system ...]", NULL}, 719 {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 720 "Disable option", "disable option .."}, 721 {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 722 "Generate a down event", "down [ccp|lcp]"}, 723 {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 724 "Enable option", "enable option .."}, 725 {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 726 "Set the link identity", "ident text..."}, 727 {"iface", "interface", RunListCommand, LOCAL_AUTH, 728 "interface control", "iface option ...", IfaceCommands}, 729 {"link", "datalink", LinkCommand, LOCAL_AUTH, 730 "Link specific commands", "link name command ..."}, 731 {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 732 "Load settings", "load [system ...]"}, 733 #ifndef NONAT 734 {"nat", "alias", RunListCommand, LOCAL_AUTH, 735 "NAT control", "nat option yes|no", NatCommands}, 736 #endif 737 {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 738 "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 739 {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 740 "Password for manipulation", "passwd LocalPassword"}, 741 {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 742 "Quit PPP program", "quit|bye [all]"}, 743 {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 744 "Remove a link", "remove"}, 745 {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 746 "Rename a link", "rename name"}, 747 {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 748 "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 749 {"save", NULL, SaveCommand, LOCAL_AUTH, 750 "Save settings", "save"}, 751 {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 752 "Transmit the link identity", "sendident"}, 753 {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 754 "Set parameters", "set[up] var value"}, 755 {"shell", "!", FgShellCommand, LOCAL_AUTH, 756 "Run a subshell", "shell|! [sh command]"}, 757 {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 758 "Show status and stats", "show var"}, 759 {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 760 "Enter terminal mode", "term"}, 761 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 762 "Display this message", "help|? [command]", Commands}, 763 {NULL, NULL, NULL}, 764 }; 765 766 static int 767 ShowEscape(struct cmdargs const *arg) 768 { 769 if (arg->cx->physical->async.cfg.EscMap[32]) { 770 int code, bit; 771 const char *sep = ""; 772 773 for (code = 0; code < 32; code++) 774 if (arg->cx->physical->async.cfg.EscMap[code]) 775 for (bit = 0; bit < 8; bit++) 776 if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 777 prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 778 sep = ", "; 779 } 780 prompt_Printf(arg->prompt, "\n"); 781 } 782 return 0; 783 } 784 785 static int 786 ShowTimerList(struct cmdargs const *arg) 787 { 788 timer_Show(0, arg->prompt); 789 return 0; 790 } 791 792 static int 793 ShowStopped(struct cmdargs const *arg) 794 { 795 prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 796 if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 797 prompt_Printf(arg->prompt, "Disabled"); 798 else 799 prompt_Printf(arg->prompt, "%ld secs", 800 arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 801 802 prompt_Printf(arg->prompt, ", CCP: "); 803 if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 804 prompt_Printf(arg->prompt, "Disabled"); 805 else 806 prompt_Printf(arg->prompt, "%ld secs", 807 arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 808 809 prompt_Printf(arg->prompt, "\n"); 810 811 return 0; 812 } 813 814 static int 815 ShowVersion(struct cmdargs const *arg) 816 { 817 prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 818 return 0; 819 } 820 821 static int 822 ShowProtocolStats(struct cmdargs const *arg) 823 { 824 struct link *l = command_ChooseLink(arg); 825 826 prompt_Printf(arg->prompt, "%s:\n", l->name); 827 link_ReportProtocolStatus(l, arg->prompt); 828 return 0; 829 } 830 831 static struct cmdtab const ShowCommands[] = { 832 {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 833 "bundle details", "show bundle"}, 834 {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 835 "CCP status", "show cpp"}, 836 {"compress", NULL, sl_Show, LOCAL_AUTH, 837 "VJ compression stats", "show compress"}, 838 {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 839 "escape characters", "show escape"}, 840 {"filter", NULL, filter_Show, LOCAL_AUTH, 841 "packet filters", "show filter [in|out|dial|alive]"}, 842 {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 843 "HDLC errors", "show hdlc"}, 844 {"iface", "interface", iface_Show, LOCAL_AUTH, 845 "Interface status", "show iface"}, 846 {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 847 "IPCP status", "show ipcp"}, 848 {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 849 "Protocol layers", "show layers"}, 850 {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 851 "LCP status", "show lcp"}, 852 {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 853 "(high-level) link info", "show link"}, 854 {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 855 "available link names", "show links"}, 856 {"log", NULL, log_ShowLevel, LOCAL_AUTH, 857 "log levels", "show log"}, 858 {"mem", NULL, mbuf_Show, LOCAL_AUTH, 859 "mbuf allocations", "show mem"}, 860 {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 861 "(low-level) link info", "show physical"}, 862 {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 863 "multilink setup", "show mp"}, 864 {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 865 "protocol summary", "show proto"}, 866 {"route", NULL, route_Show, LOCAL_AUTH, 867 "routing table", "show route"}, 868 {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 869 "STOPPED timeout", "show stopped"}, 870 {"timers", NULL, ShowTimerList, LOCAL_AUTH, 871 "alarm timers", "show timers"}, 872 {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 873 "version string", "show version"}, 874 {"who", NULL, log_ShowWho, LOCAL_AUTH, 875 "client list", "show who"}, 876 {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 877 "Display this message", "show help|? [command]", ShowCommands}, 878 {NULL, NULL, NULL}, 879 }; 880 881 static struct cmdtab const * 882 FindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 883 { 884 int nmatch; 885 int len; 886 struct cmdtab const *found; 887 888 found = NULL; 889 len = strlen(str); 890 nmatch = 0; 891 while (cmds->func) { 892 if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 893 if (cmds->name[len] == '\0') { 894 *pmatch = 1; 895 return cmds; 896 } 897 nmatch++; 898 found = cmds; 899 } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 900 if (cmds->alias[len] == '\0') { 901 *pmatch = 1; 902 return cmds; 903 } 904 nmatch++; 905 found = cmds; 906 } 907 cmds++; 908 } 909 *pmatch = nmatch; 910 return found; 911 } 912 913 static const char * 914 mkPrefix(int argc, char const *const *argv, char *tgt, int sz) 915 { 916 int f, tlen, len; 917 918 tlen = 0; 919 for (f = 0; f < argc && tlen < sz - 2; f++) { 920 if (f) 921 tgt[tlen++] = ' '; 922 len = strlen(argv[f]); 923 if (len > sz - tlen - 1) 924 len = sz - tlen - 1; 925 strncpy(tgt+tlen, argv[f], len); 926 tlen += len; 927 } 928 tgt[tlen] = '\0'; 929 return tgt; 930 } 931 932 static int 933 FindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 934 char const *const *argv, struct prompt *prompt, struct datalink *cx) 935 { 936 struct cmdtab const *cmd; 937 int val = 1; 938 int nmatch; 939 struct cmdargs arg; 940 char prefix[100]; 941 942 cmd = FindCommand(cmds, argv[argn], &nmatch); 943 if (nmatch > 1) 944 log_Printf(LogWARN, "%s: Ambiguous command\n", 945 mkPrefix(argn+1, argv, prefix, sizeof prefix)); 946 else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 947 if ((cmd->lauth & LOCAL_CX) && !cx) 948 /* We've got no context, but we require it */ 949 cx = bundle2datalink(bundle, NULL); 950 951 if ((cmd->lauth & LOCAL_CX) && !cx) 952 log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 953 mkPrefix(argn+1, argv, prefix, sizeof prefix)); 954 else { 955 if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 956 log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 957 mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 958 cx = NULL; 959 } 960 arg.cmdtab = cmds; 961 arg.cmd = cmd; 962 arg.argc = argc; 963 arg.argn = argn+1; 964 arg.argv = argv; 965 arg.bundle = bundle; 966 arg.cx = cx; 967 arg.prompt = prompt; 968 val = (*cmd->func) (&arg); 969 } 970 } else 971 log_Printf(LogWARN, "%s: Invalid command\n", 972 mkPrefix(argn+1, argv, prefix, sizeof prefix)); 973 974 if (val == -1) 975 log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 976 else if (val) 977 log_Printf(LogWARN, "%s: Failed %d\n", 978 mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 979 980 return val; 981 } 982 983 int 984 command_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 985 { 986 char buff2[LINE_LEN-offset]; 987 988 InterpretArg(buff, buff2); 989 strncpy(buff, buff2, LINE_LEN - offset - 1); 990 buff[LINE_LEN - offset - 1] = '\0'; 991 992 return command_Interpret(buff, nb, argv); 993 } 994 995 int 996 command_Interpret(char *buff, int nb, char *argv[MAXARGS]) 997 { 998 char *cp; 999 1000 if (nb > 0) { 1001 cp = buff + strcspn(buff, "\r\n"); 1002 if (cp) 1003 *cp = '\0'; 1004 return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 1005 } 1006 return 0; 1007 } 1008 1009 static int 1010 arghidden(int argc, char const *const *argv, int n) 1011 { 1012 /* Is arg n of the given command to be hidden from the log ? */ 1013 1014 /* set authkey xxxxx */ 1015 /* set key xxxxx */ 1016 if (n == 2 && !strncasecmp(argv[0], "se", 2) && 1017 (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 1018 return 1; 1019 1020 /* passwd xxxxx */ 1021 if (n == 1 && !strncasecmp(argv[0], "p", 1)) 1022 return 1; 1023 1024 /* set server port xxxxx .... */ 1025 if (n == 3 && !strncasecmp(argv[0], "se", 2) && 1026 !strncasecmp(argv[1], "se", 2)) 1027 return 1; 1028 1029 return 0; 1030 } 1031 1032 void 1033 command_Run(struct bundle *bundle, int argc, char const *const *argv, 1034 struct prompt *prompt, const char *label, struct datalink *cx) 1035 { 1036 if (argc > 0) { 1037 if (log_IsKept(LogCOMMAND)) { 1038 char buf[LINE_LEN]; 1039 int f, n; 1040 1041 if (label) { 1042 strncpy(buf, label, sizeof buf - 3); 1043 buf[sizeof buf - 3] = '\0'; 1044 strcat(buf, ": "); 1045 n = strlen(buf); 1046 } else { 1047 *buf = '\0'; 1048 n = 0; 1049 } 1050 buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 1051 1052 for (f = 0; f < argc; f++) { 1053 if (n < sizeof buf - 1 && f) 1054 buf[n++] = ' '; 1055 if (arghidden(argc, argv, f)) 1056 strncpy(buf+n, "********", sizeof buf - n - 1); 1057 else 1058 strncpy(buf+n, argv[f], sizeof buf - n - 1); 1059 n += strlen(buf+n); 1060 } 1061 log_Printf(LogCOMMAND, "%s\n", buf); 1062 } 1063 FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 1064 } 1065 } 1066 1067 int 1068 command_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 1069 const char *label) 1070 { 1071 int argc; 1072 char *argv[MAXARGS]; 1073 1074 if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 1075 return 0; 1076 1077 command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 1078 return 1; 1079 } 1080 1081 static int 1082 ShowCommand(struct cmdargs const *arg) 1083 { 1084 if (!arg->prompt) 1085 log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 1086 else if (arg->argc > arg->argn) 1087 FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 1088 arg->prompt, arg->cx); 1089 else 1090 prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 1091 1092 return 0; 1093 } 1094 1095 static int 1096 TerminalCommand(struct cmdargs const *arg) 1097 { 1098 if (!arg->prompt) { 1099 log_Printf(LogWARN, "term: Need a prompt\n"); 1100 return 1; 1101 } 1102 1103 if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 1104 prompt_Printf(arg->prompt, "LCP state is [%s]\n", 1105 State2Nam(arg->cx->physical->link.lcp.fsm.state)); 1106 return 1; 1107 } 1108 1109 datalink_Up(arg->cx, 0, 0); 1110 prompt_TtyTermMode(arg->prompt, arg->cx); 1111 return 0; 1112 } 1113 1114 static int 1115 QuitCommand(struct cmdargs const *arg) 1116 { 1117 if (!arg->prompt || prompt_IsController(arg->prompt) || 1118 (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 1119 (arg->prompt->auth & LOCAL_AUTH))) 1120 Cleanup(EX_NORMAL); 1121 if (arg->prompt) 1122 prompt_Destroy(arg->prompt, 1); 1123 1124 return 0; 1125 } 1126 1127 static int 1128 OpenCommand(struct cmdargs const *arg) 1129 { 1130 if (arg->argc == arg->argn) 1131 bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 1132 else if (arg->argc == arg->argn + 1) { 1133 if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 1134 struct datalink *cx = arg->cx ? 1135 arg->cx : bundle2datalink(arg->bundle, NULL); 1136 if (cx) { 1137 if (cx->physical->link.lcp.fsm.state == ST_OPENED) 1138 fsm_Reopen(&cx->physical->link.lcp.fsm); 1139 else 1140 bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 1141 } else 1142 log_Printf(LogWARN, "open lcp: You must specify a link\n"); 1143 } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 1144 struct fsm *fp; 1145 1146 fp = &command_ChooseLink(arg)->ccp.fsm; 1147 if (fp->link->lcp.fsm.state != ST_OPENED) 1148 log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 1149 else if (fp->state == ST_OPENED) 1150 fsm_Reopen(fp); 1151 else { 1152 fp->open_mode = 0; /* Not passive any more */ 1153 if (fp->state == ST_STOPPED) { 1154 fsm_Down(fp); 1155 fsm_Up(fp); 1156 } else { 1157 fsm_Up(fp); 1158 fsm_Open(fp); 1159 } 1160 } 1161 } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 1162 if (arg->cx) 1163 log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 1164 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 1165 fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 1166 else 1167 bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 1168 } else 1169 return -1; 1170 } else 1171 return -1; 1172 1173 return 0; 1174 } 1175 1176 static int 1177 CloseCommand(struct cmdargs const *arg) 1178 { 1179 if (arg->argc == arg->argn) 1180 bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 1181 else if (arg->argc == arg->argn + 1) { 1182 if (!strcasecmp(arg->argv[arg->argn], "lcp")) 1183 bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 1184 else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 1185 !strcasecmp(arg->argv[arg->argn], "ccp!")) { 1186 struct fsm *fp; 1187 1188 fp = &command_ChooseLink(arg)->ccp.fsm; 1189 if (fp->state == ST_OPENED) { 1190 fsm_Close(fp); 1191 if (arg->argv[arg->argn][3] == '!') 1192 fp->open_mode = 0; /* Stay ST_CLOSED */ 1193 else 1194 fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 1195 } 1196 } else 1197 return -1; 1198 } else 1199 return -1; 1200 1201 return 0; 1202 } 1203 1204 static int 1205 DownCommand(struct cmdargs const *arg) 1206 { 1207 if (arg->argc == arg->argn) { 1208 if (arg->cx) 1209 datalink_Down(arg->cx, CLOSE_STAYDOWN); 1210 else 1211 bundle_Down(arg->bundle, CLOSE_STAYDOWN); 1212 } else if (arg->argc == arg->argn + 1) { 1213 if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 1214 if (arg->cx) 1215 datalink_Down(arg->cx, CLOSE_LCP); 1216 else 1217 bundle_Down(arg->bundle, CLOSE_LCP); 1218 } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 1219 struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 1220 &arg->bundle->ncp.mp.link.ccp.fsm; 1221 fsm2initial(fp); 1222 } else 1223 return -1; 1224 } else 1225 return -1; 1226 1227 return 0; 1228 } 1229 1230 static int 1231 SetModemSpeed(struct cmdargs const *arg) 1232 { 1233 long speed; 1234 char *end; 1235 1236 if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 1237 if (arg->argc > arg->argn+1) { 1238 log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 1239 return -1; 1240 } 1241 if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 1242 physical_SetSync(arg->cx->physical); 1243 return 0; 1244 } 1245 end = NULL; 1246 speed = strtol(arg->argv[arg->argn], &end, 10); 1247 if (*end) { 1248 log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 1249 arg->argv[arg->argn]); 1250 return -1; 1251 } 1252 if (physical_SetSpeed(arg->cx->physical, speed)) 1253 return 0; 1254 log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 1255 } else 1256 log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 1257 1258 return -1; 1259 } 1260 1261 static int 1262 SetStoppedTimeout(struct cmdargs const *arg) 1263 { 1264 struct link *l = &arg->cx->physical->link; 1265 1266 l->lcp.fsm.StoppedTimer.load = 0; 1267 l->ccp.fsm.StoppedTimer.load = 0; 1268 if (arg->argc <= arg->argn+2) { 1269 if (arg->argc > arg->argn) { 1270 l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 1271 if (arg->argc > arg->argn+1) 1272 l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 1273 } 1274 return 0; 1275 } 1276 return -1; 1277 } 1278 1279 static int 1280 SetServer(struct cmdargs const *arg) 1281 { 1282 int res = -1; 1283 1284 if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 1285 const char *port, *passwd, *mask; 1286 int mlen; 1287 1288 /* What's what ? */ 1289 port = arg->argv[arg->argn]; 1290 if (arg->argc == arg->argn + 2) { 1291 passwd = arg->argv[arg->argn+1]; 1292 mask = NULL; 1293 } else if (arg->argc == arg->argn + 3) { 1294 passwd = arg->argv[arg->argn+1]; 1295 mask = arg->argv[arg->argn+2]; 1296 mlen = strlen(mask); 1297 if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 1298 (mlen == 4 && *mask != '0')) { 1299 log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 1300 arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 1301 return -1; 1302 } 1303 } else if (arg->argc != arg->argn + 1) 1304 return -1; 1305 else if (strcasecmp(port, "none") == 0) { 1306 if (server_Clear(arg->bundle)) 1307 log_Printf(LogPHASE, "Disabled server socket\n"); 1308 return 0; 1309 } else if (strcasecmp(port, "open") == 0) { 1310 switch (server_Reopen(arg->bundle)) { 1311 case SERVER_OK: 1312 return 0; 1313 case SERVER_FAILED: 1314 log_Printf(LogWARN, "Failed to reopen server port\n"); 1315 return 1; 1316 case SERVER_UNSET: 1317 log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 1318 return 1; 1319 default: 1320 break; 1321 } 1322 return -1; 1323 } else if (strcasecmp(port, "closed") == 0) { 1324 if (server_Close(arg->bundle)) 1325 log_Printf(LogPHASE, "Closed server socket\n"); 1326 else 1327 log_Printf(LogWARN, "Server socket not open\n"); 1328 1329 return 0; 1330 } else 1331 return -1; 1332 1333 strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 1334 server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 1335 1336 if (*port == '/') { 1337 mode_t imask; 1338 char *ptr, name[LINE_LEN + 12]; 1339 1340 if (mask == NULL) 1341 imask = (mode_t)-1; 1342 else for (imask = mlen = 0; mask[mlen]; mlen++) 1343 imask = (imask * 8) + mask[mlen] - '0'; 1344 1345 ptr = strstr(port, "%d"); 1346 if (ptr) { 1347 snprintf(name, sizeof name, "%.*s%d%s", 1348 (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 1349 port = name; 1350 } 1351 res = server_LocalOpen(arg->bundle, port, imask); 1352 } else { 1353 int iport, add = 0; 1354 1355 if (mask != NULL) 1356 return -1; 1357 1358 if (*port == '+') { 1359 port++; 1360 add = 1; 1361 } 1362 if (strspn(port, "0123456789") != strlen(port)) { 1363 struct servent *s; 1364 1365 if ((s = getservbyname(port, "tcp")) == NULL) { 1366 iport = 0; 1367 log_Printf(LogWARN, "%s: Invalid port or service\n", port); 1368 } else 1369 iport = ntohs(s->s_port); 1370 } else 1371 iport = atoi(port); 1372 1373 if (iport) { 1374 if (add) 1375 iport += arg->bundle->unit; 1376 res = server_TcpOpen(arg->bundle, iport); 1377 } else 1378 res = -1; 1379 } 1380 } 1381 1382 return res; 1383 } 1384 1385 static int 1386 SetEscape(struct cmdargs const *arg) 1387 { 1388 int code; 1389 int argc = arg->argc - arg->argn; 1390 char const *const *argv = arg->argv + arg->argn; 1391 1392 for (code = 0; code < 33; code++) 1393 arg->cx->physical->async.cfg.EscMap[code] = 0; 1394 1395 while (argc-- > 0) { 1396 sscanf(*argv++, "%x", &code); 1397 code &= 0xff; 1398 arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 1399 arg->cx->physical->async.cfg.EscMap[32] = 1; 1400 } 1401 return 0; 1402 } 1403 1404 static int 1405 SetInterfaceAddr(struct cmdargs const *arg) 1406 { 1407 struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 1408 const char *hisaddr; 1409 1410 if (arg->argc > arg->argn + 4) 1411 return -1; 1412 1413 hisaddr = NULL; 1414 memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 1415 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1416 ipcp->cfg.HaveTriggerAddress = 0; 1417 ipcp->cfg.netmask.s_addr = INADDR_ANY; 1418 iplist_reset(&ipcp->cfg.peer_list); 1419 1420 if (arg->argc > arg->argn) { 1421 if (!ParseAddr(ipcp, arg->argv[arg->argn], 1422 &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 1423 &ipcp->cfg.my_range.width)) 1424 return 1; 1425 if (arg->argc > arg->argn+1) { 1426 hisaddr = arg->argv[arg->argn+1]; 1427 if (arg->argc > arg->argn+2) { 1428 ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 1429 if (arg->argc > arg->argn+3) { 1430 ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 1431 ipcp->cfg.HaveTriggerAddress = 1; 1432 } 1433 } 1434 } 1435 } 1436 1437 /* 0.0.0.0 means any address (0 bits) */ 1438 if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 1439 ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 1440 ipcp->cfg.my_range.width = 0; 1441 } 1442 ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 1443 bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 1444 1445 if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 1446 arg->bundle->phys_type.all & PHYS_AUTO)) 1447 return 4; 1448 1449 return 0; 1450 } 1451 1452 static int 1453 SetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 1454 u_int *maxtrm, int def) 1455 { 1456 if (argc == 0) { 1457 *timeout = DEF_FSMRETRY; 1458 *maxreq = def; 1459 if (maxtrm != NULL) 1460 *maxtrm = def; 1461 } else { 1462 long l = atol(argv[0]); 1463 1464 if (l < MIN_FSMRETRY) { 1465 log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 1466 l, MIN_FSMRETRY); 1467 return 1; 1468 } else 1469 *timeout = l; 1470 1471 if (argc > 1) { 1472 l = atol(argv[1]); 1473 if (l < 1) { 1474 log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 1475 l = 1; 1476 } 1477 *maxreq = l; 1478 1479 if (argc > 2 && maxtrm != NULL) { 1480 l = atol(argv[2]); 1481 if (l < 1) { 1482 log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 1483 l = 1; 1484 } 1485 *maxtrm = l; 1486 } 1487 } 1488 } 1489 1490 return 0; 1491 } 1492 1493 static int 1494 SetVariable(struct cmdargs const *arg) 1495 { 1496 long long_val, param = (long)arg->cmd->args; 1497 int mode, dummyint, f, first, res; 1498 u_short *change; 1499 const char *argp; 1500 struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 1501 struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 1502 struct in_addr dummyaddr, *addr; 1503 1504 if (arg->argc > arg->argn) 1505 argp = arg->argv[arg->argn]; 1506 else 1507 argp = ""; 1508 1509 res = 0; 1510 1511 if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 1512 log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 1513 arg->cmd->name); 1514 return 1; 1515 } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 1516 log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 1517 arg->cmd->name, cx->name); 1518 cx = NULL; 1519 } 1520 1521 switch (param) { 1522 case VAR_AUTHKEY: 1523 strncpy(arg->bundle->cfg.auth.key, argp, 1524 sizeof arg->bundle->cfg.auth.key - 1); 1525 arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 1526 break; 1527 1528 case VAR_AUTHNAME: 1529 switch (bundle_Phase(arg->bundle)) { 1530 default: 1531 log_Printf(LogWARN, "Altering authname while at phase %s\n", 1532 bundle_PhaseName(arg->bundle)); 1533 /* drop through */ 1534 case PHASE_DEAD: 1535 case PHASE_ESTABLISH: 1536 strncpy(arg->bundle->cfg.auth.name, argp, 1537 sizeof arg->bundle->cfg.auth.name - 1); 1538 arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 1539 break; 1540 } 1541 break; 1542 1543 case VAR_AUTOLOAD: 1544 if (arg->argc == arg->argn + 3) { 1545 int v1, v2, v3; 1546 char *end; 1547 1548 v1 = strtol(arg->argv[arg->argn], &end, 0); 1549 if (v1 < 0 || *end) { 1550 log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 1551 arg->argv[arg->argn]); 1552 res = 1; 1553 break; 1554 } 1555 1556 v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 1557 if (v2 < 0 || *end) { 1558 log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 1559 arg->argv[arg->argn + 1]); 1560 res = 1; 1561 break; 1562 } 1563 if (v2 < v1) { 1564 v3 = v1; 1565 v1 = v2; 1566 v2 = v3; 1567 } 1568 1569 v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 1570 if (v3 <= 0 || *end) { 1571 log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 1572 arg->argv[arg->argn + 2]); 1573 res = 1; 1574 break; 1575 } 1576 1577 arg->bundle->ncp.mp.cfg.autoload.min = v1; 1578 arg->bundle->ncp.mp.cfg.autoload.max = v2; 1579 arg->bundle->ncp.mp.cfg.autoload.period = v3; 1580 mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 1581 } else { 1582 log_Printf(LogWARN, "Set autoload requires three arguments\n"); 1583 res = 1; 1584 } 1585 break; 1586 1587 case VAR_DIAL: 1588 strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 1589 cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 1590 break; 1591 1592 case VAR_LOGIN: 1593 strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 1594 cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 1595 break; 1596 1597 case VAR_WINSIZE: 1598 if (arg->argc > arg->argn) { 1599 l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 1600 if (l->ccp.cfg.deflate.out.winsize < 8 || 1601 l->ccp.cfg.deflate.out.winsize > 15) { 1602 log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 1603 l->ccp.cfg.deflate.out.winsize); 1604 l->ccp.cfg.deflate.out.winsize = 15; 1605 } 1606 if (arg->argc > arg->argn+1) { 1607 l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 1608 if (l->ccp.cfg.deflate.in.winsize < 8 || 1609 l->ccp.cfg.deflate.in.winsize > 15) { 1610 log_Printf(LogWARN, "%d: Invalid incoming window size\n", 1611 l->ccp.cfg.deflate.in.winsize); 1612 l->ccp.cfg.deflate.in.winsize = 15; 1613 } 1614 } else 1615 l->ccp.cfg.deflate.in.winsize = 0; 1616 } else { 1617 log_Printf(LogWARN, "No window size specified\n"); 1618 res = 1; 1619 } 1620 break; 1621 1622 #ifdef HAVE_DES 1623 case VAR_MPPE: 1624 if (arg->argc > arg->argn + 2) { 1625 res = -1; 1626 break; 1627 } 1628 1629 if (arg->argc == arg->argn) { 1630 l->ccp.cfg.mppe.keybits = 0; 1631 l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 1632 l->ccp.cfg.mppe.required = 0; 1633 break; 1634 } 1635 1636 if (!strcmp(argp, "*")) 1637 long_val = 0; 1638 else { 1639 long_val = atol(argp); 1640 if (long_val != 40 && long_val != 56 && long_val != 128) { 1641 log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 1642 res = -1; 1643 break; 1644 } 1645 } 1646 1647 if (arg->argc == arg->argn + 2) { 1648 if (!strcmp(arg->argv[arg->argn + 1], "*")) 1649 l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 1650 else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 1651 l->ccp.cfg.mppe.state = MPPE_STATELESS; 1652 else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 1653 l->ccp.cfg.mppe.state = MPPE_STATEFUL; 1654 else { 1655 log_Printf(LogWARN, "%s: Invalid state value\n", 1656 arg->argv[arg->argn + 1]); 1657 res = -1; 1658 break; 1659 } 1660 } else 1661 l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 1662 l->ccp.cfg.mppe.keybits = long_val; 1663 l->ccp.cfg.mppe.required = 1; 1664 break; 1665 #endif 1666 1667 case VAR_DEVICE: 1668 physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 1669 arg->argv + arg->argn); 1670 break; 1671 1672 case VAR_ACCMAP: 1673 if (arg->argc > arg->argn) { 1674 u_long ulong_val; 1675 sscanf(argp, "%lx", &ulong_val); 1676 cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 1677 } else { 1678 log_Printf(LogWARN, "No accmap specified\n"); 1679 res = 1; 1680 } 1681 break; 1682 1683 case VAR_MODE: 1684 mode = Nam2mode(argp); 1685 if (mode == PHYS_NONE || mode == PHYS_ALL) { 1686 log_Printf(LogWARN, "%s: Invalid mode\n", argp); 1687 res = -1; 1688 break; 1689 } 1690 bundle_SetMode(arg->bundle, cx, mode); 1691 break; 1692 1693 case VAR_MRRU: 1694 switch (bundle_Phase(arg->bundle)) { 1695 case PHASE_DEAD: 1696 break; 1697 case PHASE_ESTABLISH: 1698 /* Make sure none of our links are DATALINK_LCP or greater */ 1699 if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 1700 log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 1701 res = 1; 1702 break; 1703 } 1704 break; 1705 default: 1706 log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 1707 res = 1; 1708 break; 1709 } 1710 if (res != 0) 1711 break; 1712 long_val = atol(argp); 1713 if (long_val && long_val < MIN_MRU) { 1714 log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 1715 res = 1; 1716 break; 1717 } else if (long_val > MAX_MRU) { 1718 log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 1719 res = 1; 1720 break; 1721 } else 1722 arg->bundle->ncp.mp.cfg.mrru = long_val; 1723 break; 1724 1725 case VAR_MRU: 1726 long_val = 0; /* silence gcc */ 1727 change = NULL; /* silence gcc */ 1728 switch(arg->argc - arg->argn) { 1729 case 1: 1730 if (argp[strspn(argp, "0123456789")] != '\0') { 1731 res = -1; 1732 break; 1733 } 1734 /*FALLTHRU*/ 1735 case 0: 1736 long_val = atol(argp); 1737 change = &l->lcp.cfg.mru; 1738 if (long_val > l->lcp.cfg.max_mru) { 1739 log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 1740 l->lcp.cfg.max_mru); 1741 res = 1; 1742 break; 1743 } 1744 break; 1745 case 2: 1746 if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 1747 res = -1; 1748 break; 1749 } 1750 long_val = atol(arg->argv[arg->argn + 1]); 1751 change = &l->lcp.cfg.max_mru; 1752 if (long_val > MAX_MRU) { 1753 log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 1754 MAX_MRU); 1755 res = 1; 1756 break; 1757 } 1758 break; 1759 default: 1760 res = -1; 1761 break; 1762 } 1763 if (res != 0) 1764 break; 1765 1766 if (long_val == 0) 1767 *change = 0; 1768 else if (long_val < MIN_MRU) { 1769 log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 1770 res = 1; 1771 break; 1772 } else if (long_val > MAX_MRU) { 1773 log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 1774 res = 1; 1775 break; 1776 } else 1777 *change = long_val; 1778 if (l->lcp.cfg.mru > *change) 1779 l->lcp.cfg.mru = *change; 1780 break; 1781 1782 case VAR_MTU: 1783 long_val = 0; /* silence gcc */ 1784 change = NULL; /* silence gcc */ 1785 switch(arg->argc - arg->argn) { 1786 case 1: 1787 if (argp[strspn(argp, "0123456789")] != '\0') { 1788 res = -1; 1789 break; 1790 } 1791 /*FALLTHRU*/ 1792 case 0: 1793 long_val = atol(argp); 1794 change = &l->lcp.cfg.mtu; 1795 if (long_val > l->lcp.cfg.max_mtu) { 1796 log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 1797 l->lcp.cfg.max_mtu); 1798 res = 1; 1799 break; 1800 } 1801 break; 1802 case 2: 1803 if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 1804 res = -1; 1805 break; 1806 } 1807 long_val = atol(arg->argv[arg->argn + 1]); 1808 change = &l->lcp.cfg.max_mtu; 1809 if (long_val > MAX_MTU) { 1810 log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 1811 MAX_MTU); 1812 res = 1; 1813 break; 1814 } 1815 break; 1816 default: 1817 res = -1; 1818 break; 1819 } 1820 1821 if (res != 0) 1822 break; 1823 1824 if (long_val && long_val < MIN_MTU) { 1825 log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 1826 res = 1; 1827 break; 1828 } else if (long_val > MAX_MTU) { 1829 log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 1830 res = 1; 1831 break; 1832 } else 1833 *change = long_val; 1834 if (l->lcp.cfg.mtu > *change) 1835 l->lcp.cfg.mtu = *change; 1836 break; 1837 1838 case VAR_OPENMODE: 1839 if (strcasecmp(argp, "active") == 0) 1840 cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 1841 atoi(arg->argv[arg->argn+1]) : 1; 1842 else if (strcasecmp(argp, "passive") == 0) 1843 cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 1844 else { 1845 log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 1846 res = 1; 1847 } 1848 break; 1849 1850 case VAR_PHONE: 1851 strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 1852 cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 1853 cx->phone.alt = cx->phone.next = NULL; 1854 break; 1855 1856 case VAR_HANGUP: 1857 strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 1858 cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 1859 break; 1860 1861 case VAR_IFQUEUE: 1862 long_val = atol(argp); 1863 arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 1864 break; 1865 1866 case VAR_LOGOUT: 1867 strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 1868 cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 1869 break; 1870 1871 case VAR_IDLETIMEOUT: 1872 if (arg->argc > arg->argn+2) { 1873 log_Printf(LogWARN, "Too many idle timeout values\n"); 1874 res = 1; 1875 } else if (arg->argc == arg->argn) { 1876 log_Printf(LogWARN, "Too few idle timeout values\n"); 1877 res = 1; 1878 } else { 1879 int timeout, min; 1880 1881 timeout = atoi(argp); 1882 min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 1883 bundle_SetIdleTimer(arg->bundle, timeout, min); 1884 } 1885 break; 1886 1887 case VAR_LQRPERIOD: 1888 long_val = atol(argp); 1889 if (long_val < MIN_LQRPERIOD) { 1890 log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 1891 long_val, MIN_LQRPERIOD); 1892 res = 1; 1893 } else 1894 l->lcp.cfg.lqrperiod = long_val; 1895 break; 1896 1897 case VAR_LCPRETRY: 1898 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1899 &cx->physical->link.lcp.cfg.fsm.timeout, 1900 &cx->physical->link.lcp.cfg.fsm.maxreq, 1901 &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 1902 break; 1903 1904 case VAR_CHAPRETRY: 1905 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1906 &cx->chap.auth.cfg.fsm.timeout, 1907 &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 1908 break; 1909 1910 case VAR_PAPRETRY: 1911 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1912 &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 1913 NULL, DEF_FSMAUTHTRIES); 1914 break; 1915 1916 case VAR_CCPRETRY: 1917 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1918 &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 1919 &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 1920 break; 1921 1922 case VAR_IPCPRETRY: 1923 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1924 &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 1925 &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 1926 &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 1927 break; 1928 1929 case VAR_NBNS: 1930 case VAR_DNS: 1931 if (param == VAR_DNS) { 1932 addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 1933 addr[0].s_addr = addr[1].s_addr = INADDR_NONE; 1934 } else { 1935 addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 1936 addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1937 } 1938 1939 if (arg->argc > arg->argn) { 1940 ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 1941 addr, &dummyaddr, &dummyint); 1942 if (arg->argc > arg->argn+1) 1943 ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 1944 addr + 1, &dummyaddr, &dummyint); 1945 1946 if (addr[0].s_addr == INADDR_ANY) { 1947 addr[0].s_addr = addr[1].s_addr; 1948 addr[1].s_addr = INADDR_ANY; 1949 } 1950 if (addr[0].s_addr == INADDR_NONE) { 1951 addr[0].s_addr = addr[1].s_addr; 1952 addr[1].s_addr = INADDR_NONE; 1953 } 1954 } 1955 break; 1956 1957 case VAR_CALLBACK: 1958 cx->cfg.callback.opmask = 0; 1959 for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 1960 if (!strcasecmp(arg->argv[dummyint], "auth")) 1961 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 1962 else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 1963 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 1964 else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 1965 if (dummyint == arg->argc - 1) 1966 log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 1967 else { 1968 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 1969 strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 1970 sizeof cx->cfg.callback.msg - 1); 1971 cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 1972 } 1973 } else if (!strcasecmp(arg->argv[dummyint], "none")) 1974 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 1975 else { 1976 res = -1; 1977 break; 1978 } 1979 } 1980 if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 1981 cx->cfg.callback.opmask = 0; 1982 break; 1983 1984 case VAR_CBCP: 1985 cx->cfg.cbcp.delay = 0; 1986 *cx->cfg.cbcp.phone = '\0'; 1987 cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 1988 if (arg->argc > arg->argn) { 1989 strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 1990 sizeof cx->cfg.cbcp.phone - 1); 1991 cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 1992 if (arg->argc > arg->argn + 1) { 1993 cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 1994 if (arg->argc > arg->argn + 2) { 1995 long_val = atol(arg->argv[arg->argn + 2]); 1996 if (long_val < MIN_FSMRETRY) 1997 log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 1998 long_val, MIN_FSMRETRY); 1999 else 2000 cx->cfg.cbcp.fsmretry = long_val; 2001 } 2002 } 2003 } 2004 break; 2005 2006 case VAR_CHOKED: 2007 arg->bundle->cfg.choked.timeout = atoi(argp); 2008 if (arg->bundle->cfg.choked.timeout <= 0) 2009 arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 2010 break; 2011 2012 case VAR_SENDPIPE: 2013 long_val = atol(argp); 2014 arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 2015 break; 2016 2017 case VAR_RECVPIPE: 2018 long_val = atol(argp); 2019 arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 2020 break; 2021 2022 #ifndef NORADIUS 2023 case VAR_RADIUS: 2024 if (!*argp) 2025 *arg->bundle->radius.cfg.file = '\0'; 2026 else if (access(argp, R_OK)) { 2027 log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 2028 res = 1; 2029 break; 2030 } else { 2031 strncpy(arg->bundle->radius.cfg.file, argp, 2032 sizeof arg->bundle->radius.cfg.file - 1); 2033 arg->bundle->radius.cfg.file 2034 [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 2035 } 2036 break; 2037 #endif 2038 2039 case VAR_CD: 2040 if (*argp) { 2041 if (strcasecmp(argp, "off")) { 2042 long_val = atol(argp); 2043 if (long_val < 0) 2044 long_val = 0; 2045 cx->physical->cfg.cd.delay = long_val; 2046 cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 2047 CD_REQUIRED : CD_VARIABLE; 2048 } else 2049 cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 2050 } else { 2051 cx->physical->cfg.cd.delay = 0; 2052 cx->physical->cfg.cd.necessity = CD_DEFAULT; 2053 } 2054 break; 2055 2056 case VAR_PARITY: 2057 if (arg->argc == arg->argn + 1) 2058 res = physical_SetParity(arg->cx->physical, argp); 2059 else { 2060 log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 2061 res = 1; 2062 } 2063 break; 2064 2065 case VAR_CRTSCTS: 2066 if (strcasecmp(argp, "on") == 0) 2067 physical_SetRtsCts(arg->cx->physical, 1); 2068 else if (strcasecmp(argp, "off") == 0) 2069 physical_SetRtsCts(arg->cx->physical, 0); 2070 else { 2071 log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 2072 res = 1; 2073 } 2074 break; 2075 2076 case VAR_URGENTPORTS: 2077 if (arg->argn == arg->argc) { 2078 ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 2079 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2080 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2081 } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 2082 ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 2083 if (arg->argn == arg->argc - 1) 2084 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2085 else for (f = arg->argn + 1; f < arg->argc; f++) 2086 if (*arg->argv[f] == '+') 2087 ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 2088 else if (*arg->argv[f] == '-') 2089 ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp, 2090 atoi(arg->argv[f] + 1)); 2091 else { 2092 if (f == arg->argn) 2093 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2094 ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 2095 } 2096 } else if (arg->argn == arg->argc - 1 && 2097 !strcasecmp(arg->argv[arg->argn], "none")) { 2098 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2099 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2100 ipcp_ClearUrgentTOS(&arg->bundle->ncp.ipcp); 2101 } else { 2102 ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 2103 first = arg->argn; 2104 if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 2105 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2106 2107 for (f = first; f < arg->argc; f++) 2108 if (*arg->argv[f] == '+') 2109 ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 2110 else if (*arg->argv[f] == '-') 2111 ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp, 2112 atoi(arg->argv[f] + 1)); 2113 else { 2114 if (f == first) 2115 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2116 ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 2117 } 2118 } 2119 break; 2120 } 2121 2122 return res; 2123 } 2124 2125 static struct cmdtab const SetCommands[] = { 2126 {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2127 "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 2128 {"authkey", "key", SetVariable, LOCAL_AUTH, 2129 "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 2130 {"authname", NULL, SetVariable, LOCAL_AUTH, 2131 "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 2132 {"autoload", NULL, SetVariable, LOCAL_AUTH, 2133 "auto link [de]activation", "set autoload maxtime maxload mintime minload", 2134 (const void *)VAR_AUTOLOAD}, 2135 {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 2136 "datalink bandwidth", "set bandwidth value"}, 2137 {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2138 "callback control", "set callback [none|auth|cbcp|" 2139 "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 2140 {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2141 "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 2142 (const void *)VAR_CBCP}, 2143 {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2144 "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 2145 {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 2146 "set cd value[!]", (const void *)VAR_CD}, 2147 {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 2148 "CHAP retries", "set chapretry value [attempts]", 2149 (const void *)VAR_CHAPRETRY}, 2150 {"choked", NULL, SetVariable, LOCAL_AUTH, 2151 "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 2152 {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 2153 "Use hardware flow control", "set ctsrts [on|off]", 2154 (const char *)VAR_CRTSCTS}, 2155 {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2156 "deflate window sizes", "set deflate out-winsize in-winsize", 2157 (const void *) VAR_WINSIZE}, 2158 #ifdef HAVE_DES 2159 {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2160 "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 2161 (const void *) VAR_MPPE}, 2162 #endif 2163 {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 2164 "physical device name", "set device|line device-name[,device-name]", 2165 (const void *) VAR_DEVICE}, 2166 {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2167 "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 2168 {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 2169 "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 2170 {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 2171 "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 2172 {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 2173 "escape characters", "set escape hex-digit ..."}, 2174 {"filter", NULL, filter_Set, LOCAL_AUTH, 2175 "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 2176 "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 2177 "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 2178 {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2179 "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 2180 {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 2181 "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 2182 {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 2183 "set ifqueue packets", (const void *)VAR_IFQUEUE}, 2184 {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 2185 "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 2186 {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 2187 "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 2188 {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 2189 "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 2190 "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 2191 {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2192 "login script", "set login chat-script", (const void *) VAR_LOGIN}, 2193 {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2194 "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 2195 {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2196 "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 2197 {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 2198 "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 2199 {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 2200 "set mrru value", (const void *)VAR_MRRU}, 2201 {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2202 "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 2203 {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2204 "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 2205 {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 2206 "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 2207 {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 2208 "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 2209 {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 2210 "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 2211 {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 2212 "set parity [odd|even|none]", (const void *)VAR_PARITY}, 2213 {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 2214 "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 2215 {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 2216 "Process title", "set proctitle [value]"}, 2217 #ifndef NORADIUS 2218 {"radius", NULL, SetVariable, LOCAL_AUTH, 2219 "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 2220 #endif 2221 {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 2222 "Reconnect timeout", "set reconnect value ntries"}, 2223 {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 2224 "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 2225 {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 2226 "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 2227 {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 2228 "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 2229 {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 2230 "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 2231 {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 2232 "physical speed", "set speed value|sync"}, 2233 {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 2234 "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 2235 {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 2236 "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 2237 {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 2238 "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 2239 {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 2240 "vj values", "set vj slots|slotcomp [value]"}, 2241 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 2242 "Display this message", "set help|? [command]", SetCommands}, 2243 {NULL, NULL, NULL}, 2244 }; 2245 2246 static int 2247 SetCommand(struct cmdargs const *arg) 2248 { 2249 if (arg->argc > arg->argn) 2250 FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 2251 arg->prompt, arg->cx); 2252 else if (arg->prompt) 2253 prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 2254 " syntax help.\n"); 2255 else 2256 log_Printf(LogWARN, "set command must have arguments\n"); 2257 2258 return 0; 2259 } 2260 2261 static int 2262 AddCommand(struct cmdargs const *arg) 2263 { 2264 struct in_addr dest, gateway, netmask; 2265 int gw, addrs; 2266 2267 if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 2268 return -1; 2269 2270 addrs = 0; 2271 if (arg->argc == arg->argn+2) { 2272 if (!strcasecmp(arg->argv[arg->argn], "default")) 2273 dest.s_addr = netmask.s_addr = INADDR_ANY; 2274 else { 2275 int width; 2276 2277 if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 2278 &dest, &netmask, &width)) 2279 return -1; 2280 if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 2281 addrs = ROUTE_DSTMYADDR; 2282 else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 2283 addrs = ROUTE_DSTHISADDR; 2284 else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 2285 addrs = ROUTE_DSTDNS0; 2286 else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 2287 addrs = ROUTE_DSTDNS1; 2288 } 2289 gw = 1; 2290 } else { 2291 if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 2292 addrs = ROUTE_DSTMYADDR; 2293 dest = arg->bundle->ncp.ipcp.my_ip; 2294 } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 2295 addrs = ROUTE_DSTHISADDR; 2296 dest = arg->bundle->ncp.ipcp.peer_ip; 2297 } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 2298 addrs = ROUTE_DSTDNS0; 2299 dest = arg->bundle->ncp.ipcp.ns.dns[0]; 2300 } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 2301 addrs = ROUTE_DSTDNS1; 2302 dest = arg->bundle->ncp.ipcp.ns.dns[1]; 2303 } else { 2304 dest = GetIpAddr(arg->argv[arg->argn]); 2305 if (dest.s_addr == INADDR_NONE) { 2306 log_Printf(LogWARN, "%s: Invalid destination address\n", 2307 arg->argv[arg->argn]); 2308 return -1; 2309 } 2310 } 2311 netmask = GetIpAddr(arg->argv[arg->argn+1]); 2312 gw = 2; 2313 } 2314 2315 if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 2316 gateway = arg->bundle->ncp.ipcp.peer_ip; 2317 addrs |= ROUTE_GWHISADDR; 2318 } else { 2319 gateway = GetIpAddr(arg->argv[arg->argn+gw]); 2320 if (gateway.s_addr == INADDR_NONE) { 2321 log_Printf(LogWARN, "%s: Invalid gateway address\n", 2322 arg->argv[arg->argn + gw]); 2323 return -1; 2324 } 2325 } 2326 2327 if (rt_Set(arg->bundle, RTM_ADD, dest, gateway, netmask, 2328 arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 2329 && addrs != ROUTE_STATIC) 2330 route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 2331 2332 return 0; 2333 } 2334 2335 static int 2336 DeleteCommand(struct cmdargs const *arg) 2337 { 2338 struct in_addr dest, none; 2339 int addrs; 2340 2341 if (arg->argc == arg->argn+1) { 2342 if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 2343 route_IfDelete(arg->bundle, 0); 2344 route_DeleteAll(&arg->bundle->ncp.ipcp.route); 2345 } else { 2346 addrs = 0; 2347 if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 2348 dest = arg->bundle->ncp.ipcp.my_ip; 2349 addrs = ROUTE_DSTMYADDR; 2350 } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 2351 dest = arg->bundle->ncp.ipcp.peer_ip; 2352 addrs = ROUTE_DSTHISADDR; 2353 } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 2354 dest = arg->bundle->ncp.ipcp.ns.dns[0]; 2355 addrs = ROUTE_DSTDNS0; 2356 } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 2357 dest = arg->bundle->ncp.ipcp.ns.dns[1]; 2358 addrs = ROUTE_DSTDNS1; 2359 } else { 2360 dest = GetIpAddr(arg->argv[arg->argn]); 2361 if (dest.s_addr == INADDR_NONE) { 2362 log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 2363 return -1; 2364 } 2365 addrs = ROUTE_STATIC; 2366 } 2367 none.s_addr = INADDR_ANY; 2368 rt_Set(arg->bundle, RTM_DELETE, dest, none, none, 2369 arg->cmd->args ? 1 : 0, 0); 2370 route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 2371 } 2372 } else 2373 return -1; 2374 2375 return 0; 2376 } 2377 2378 #ifndef NONAT 2379 static int 2380 NatEnable(struct cmdargs const *arg) 2381 { 2382 if (arg->argc == arg->argn+1) { 2383 if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 2384 if (!arg->bundle->NatEnabled) { 2385 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 2386 PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 2387 arg->bundle->NatEnabled = 1; 2388 } 2389 return 0; 2390 } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 2391 arg->bundle->NatEnabled = 0; 2392 arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 2393 /* Don't iface_Clear() - there may be manually configured addresses */ 2394 return 0; 2395 } 2396 } 2397 2398 return -1; 2399 } 2400 2401 2402 static int 2403 NatOption(struct cmdargs const *arg) 2404 { 2405 long param = (long)arg->cmd->args; 2406 2407 if (arg->argc == arg->argn+1) { 2408 if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 2409 if (arg->bundle->NatEnabled) { 2410 PacketAliasSetMode(param, param); 2411 return 0; 2412 } 2413 log_Printf(LogWARN, "nat not enabled\n"); 2414 } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 2415 if (arg->bundle->NatEnabled) { 2416 PacketAliasSetMode(0, param); 2417 return 0; 2418 } 2419 log_Printf(LogWARN, "nat not enabled\n"); 2420 } 2421 } 2422 return -1; 2423 } 2424 #endif /* #ifndef NONAT */ 2425 2426 static int 2427 LinkCommand(struct cmdargs const *arg) 2428 { 2429 if (arg->argc > arg->argn+1) { 2430 char namelist[LINE_LEN]; 2431 struct datalink *cx; 2432 char *name; 2433 int result = 0; 2434 2435 if (!strcmp(arg->argv[arg->argn], "*")) { 2436 struct datalink *dl; 2437 2438 cx = arg->bundle->links; 2439 while (cx) { 2440 /* Watch it, the command could be a ``remove'' */ 2441 dl = cx->next; 2442 FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 2443 arg->prompt, cx); 2444 for (cx = arg->bundle->links; cx; cx = cx->next) 2445 if (cx == dl) 2446 break; /* Pointer's still valid ! */ 2447 } 2448 } else { 2449 strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 2450 namelist[sizeof namelist - 1] = '\0'; 2451 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 2452 if (!bundle2datalink(arg->bundle, name)) { 2453 log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 2454 return 1; 2455 } 2456 2457 strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 2458 namelist[sizeof namelist - 1] = '\0'; 2459 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 2460 cx = bundle2datalink(arg->bundle, name); 2461 if (cx) 2462 FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 2463 arg->prompt, cx); 2464 else { 2465 log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 2466 result++; 2467 } 2468 } 2469 } 2470 return result; 2471 } 2472 2473 log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 2474 return 2; 2475 } 2476 2477 struct link * 2478 command_ChooseLink(struct cmdargs const *arg) 2479 { 2480 if (arg->cx) 2481 return &arg->cx->physical->link; 2482 else if (!arg->bundle->ncp.mp.cfg.mrru) { 2483 struct datalink *dl = bundle2datalink(arg->bundle, NULL); 2484 if (dl) 2485 return &dl->physical->link; 2486 } 2487 return &arg->bundle->ncp.mp.link; 2488 } 2489 2490 static const char * 2491 ident_cmd(const char *cmd, unsigned *keep, unsigned *add) 2492 { 2493 const char *result; 2494 2495 switch (*cmd) { 2496 case 'A': 2497 case 'a': 2498 result = "accept"; 2499 *keep = NEG_MYMASK; 2500 *add = NEG_ACCEPTED; 2501 break; 2502 case 'D': 2503 case 'd': 2504 switch (cmd[1]) { 2505 case 'E': 2506 case 'e': 2507 result = "deny"; 2508 *keep = NEG_MYMASK; 2509 *add = 0; 2510 break; 2511 case 'I': 2512 case 'i': 2513 result = "disable"; 2514 *keep = NEG_HISMASK; 2515 *add = 0; 2516 break; 2517 default: 2518 return NULL; 2519 } 2520 break; 2521 case 'E': 2522 case 'e': 2523 result = "enable"; 2524 *keep = NEG_HISMASK; 2525 *add = NEG_ENABLED; 2526 break; 2527 default: 2528 return NULL; 2529 } 2530 2531 return result; 2532 } 2533 2534 static int 2535 OptSet(struct cmdargs const *arg) 2536 { 2537 int bit = (int)(long)arg->cmd->args; 2538 const char *cmd; 2539 unsigned keep; /* Keep these bits */ 2540 unsigned add; /* Add these bits */ 2541 2542 if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 2543 return 1; 2544 2545 if (add) 2546 arg->bundle->cfg.opt |= bit; 2547 else 2548 arg->bundle->cfg.opt &= ~bit; 2549 return 0; 2550 } 2551 2552 static int 2553 IfaceAliasOptSet(struct cmdargs const *arg) 2554 { 2555 unsigned save = arg->bundle->cfg.opt; 2556 int result = OptSet(arg); 2557 2558 if (result == 0) 2559 if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 2560 arg->bundle->cfg.opt = save; 2561 log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 2562 result = 2; 2563 } 2564 2565 return result; 2566 } 2567 2568 static int 2569 NegotiateSet(struct cmdargs const *arg) 2570 { 2571 long param = (long)arg->cmd->args; 2572 struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 2573 struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 2574 const char *cmd; 2575 unsigned keep; /* Keep these bits */ 2576 unsigned add; /* Add these bits */ 2577 2578 if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 2579 return 1; 2580 2581 if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 2582 log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 2583 cmd, arg->cmd->name); 2584 return 2; 2585 } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 2586 log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 2587 cmd, arg->cmd->name, cx->name); 2588 cx = NULL; 2589 } 2590 2591 switch (param) { 2592 case NEG_ACFCOMP: 2593 cx->physical->link.lcp.cfg.acfcomp &= keep; 2594 cx->physical->link.lcp.cfg.acfcomp |= add; 2595 break; 2596 case NEG_CHAP05: 2597 cx->physical->link.lcp.cfg.chap05 &= keep; 2598 cx->physical->link.lcp.cfg.chap05 |= add; 2599 break; 2600 #ifdef HAVE_DES 2601 case NEG_CHAP80: 2602 cx->physical->link.lcp.cfg.chap80nt &= keep; 2603 cx->physical->link.lcp.cfg.chap80nt |= add; 2604 break; 2605 case NEG_CHAP80LM: 2606 cx->physical->link.lcp.cfg.chap80lm &= keep; 2607 cx->physical->link.lcp.cfg.chap80lm |= add; 2608 break; 2609 case NEG_CHAP81: 2610 cx->physical->link.lcp.cfg.chap81 &= keep; 2611 cx->physical->link.lcp.cfg.chap81 |= add; 2612 break; 2613 case NEG_MPPE: 2614 l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 2615 l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 2616 break; 2617 #endif 2618 case NEG_DEFLATE: 2619 l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 2620 l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 2621 break; 2622 case NEG_DNS: 2623 arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 2624 arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 2625 break; 2626 case NEG_ENDDISC: 2627 arg->bundle->ncp.mp.cfg.negenddisc &= keep; 2628 arg->bundle->ncp.mp.cfg.negenddisc |= add; 2629 break; 2630 case NEG_LQR: 2631 cx->physical->link.lcp.cfg.lqr &= keep; 2632 cx->physical->link.lcp.cfg.lqr |= add; 2633 break; 2634 case NEG_PAP: 2635 cx->physical->link.lcp.cfg.pap &= keep; 2636 cx->physical->link.lcp.cfg.pap |= add; 2637 break; 2638 case NEG_PPPDDEFLATE: 2639 l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 2640 l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 2641 break; 2642 case NEG_PRED1: 2643 l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 2644 l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 2645 break; 2646 case NEG_PROTOCOMP: 2647 cx->physical->link.lcp.cfg.protocomp &= keep; 2648 cx->physical->link.lcp.cfg.protocomp |= add; 2649 break; 2650 case NEG_SHORTSEQ: 2651 switch (bundle_Phase(arg->bundle)) { 2652 case PHASE_DEAD: 2653 break; 2654 case PHASE_ESTABLISH: 2655 /* Make sure none of our links are DATALINK_LCP or greater */ 2656 if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 2657 log_Printf(LogWARN, "shortseq: Only changable before" 2658 " LCP negotiations\n"); 2659 return 1; 2660 } 2661 break; 2662 default: 2663 log_Printf(LogWARN, "shortseq: Only changable at phase" 2664 " DEAD/ESTABLISH\n"); 2665 return 1; 2666 } 2667 arg->bundle->ncp.mp.cfg.shortseq &= keep; 2668 arg->bundle->ncp.mp.cfg.shortseq |= add; 2669 break; 2670 case NEG_VJCOMP: 2671 arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 2672 arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 2673 break; 2674 } 2675 2676 return 0; 2677 } 2678 2679 static struct cmdtab const NegotiateCommands[] = { 2680 {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 2681 "filter on PPPoUDP payloads", "disable|enable", 2682 (const void *)OPT_FILTERDECAP}, 2683 {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 2684 "disable|enable", (const void *)OPT_IDCHECK}, 2685 {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 2686 "retain interface addresses", "disable|enable", 2687 (const void *)OPT_IFACEALIAS}, 2688 {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 2689 "disable|enable", (const void *)OPT_KEEPSESSION}, 2690 {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 2691 "disable|enable", (const void *)OPT_LOOPBACK}, 2692 {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 2693 "disable|enable", (const void *)OPT_PASSWDAUTH}, 2694 {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 2695 "disable|enable", (const void *)OPT_PROXY}, 2696 {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 2697 "disable|enable", (const void *)OPT_PROXYALL}, 2698 {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 2699 "disable|enable", (const void *)OPT_SROUTES}, 2700 {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 2701 "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 2702 {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 2703 "disable|enable", (const void *)OPT_THROUGHPUT}, 2704 {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 2705 "disable|enable", (const void *)OPT_UTMP}, 2706 2707 #define OPT_MAX 11 /* accept/deny allowed below and not above */ 2708 2709 {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2710 "Address & Control field compression", "accept|deny|disable|enable", 2711 (const void *)NEG_ACFCOMP}, 2712 {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2713 "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 2714 (const void *)NEG_CHAP05}, 2715 #ifdef HAVE_DES 2716 {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2717 "Microsoft (NT) CHAP", "accept|deny|disable|enable", 2718 (const void *)NEG_CHAP80}, 2719 {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2720 "Microsoft (NT) CHAP", "accept|deny|disable|enable", 2721 (const void *)NEG_CHAP80LM}, 2722 {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2723 "Microsoft CHAP v2", "accept|deny|disable|enable", 2724 (const void *)NEG_CHAP81}, 2725 {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2726 "MPPE encryption", "accept|deny|disable|enable", 2727 (const void *)NEG_MPPE}, 2728 #endif 2729 {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2730 "Deflate compression", "accept|deny|disable|enable", 2731 (const void *)NEG_DEFLATE}, 2732 {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2733 "Deflate (type 24) compression", "accept|deny|disable|enable", 2734 (const void *)NEG_PPPDDEFLATE}, 2735 {"dns", NULL, NegotiateSet, LOCAL_AUTH, 2736 "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 2737 {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 2738 "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 2739 {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2740 "Link Quality Reports", "accept|deny|disable|enable", 2741 (const void *)NEG_LQR}, 2742 {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2743 "Password Authentication protocol", "accept|deny|disable|enable", 2744 (const void *)NEG_PAP}, 2745 {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2746 "Predictor 1 compression", "accept|deny|disable|enable", 2747 (const void *)NEG_PRED1}, 2748 {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2749 "Protocol field compression", "accept|deny|disable|enable", 2750 (const void *)NEG_PROTOCOMP}, 2751 {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 2752 "MP Short Sequence Numbers", "accept|deny|disable|enable", 2753 (const void *)NEG_SHORTSEQ}, 2754 {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 2755 "Van Jacobson header compression", "accept|deny|disable|enable", 2756 (const void *)NEG_VJCOMP}, 2757 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 2758 "Display this message", "accept|deny|disable|enable help|? [value]", 2759 NegotiateCommands}, 2760 {NULL, NULL, NULL}, 2761 }; 2762 2763 static int 2764 NegotiateCommand(struct cmdargs const *arg) 2765 { 2766 if (arg->argc > arg->argn) { 2767 char const *argv[3]; 2768 unsigned keep, add; 2769 int n; 2770 2771 if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 2772 return -1; 2773 argv[2] = NULL; 2774 2775 for (n = arg->argn; n < arg->argc; n++) { 2776 argv[1] = arg->argv[n]; 2777 FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 2778 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 2779 } 2780 } else if (arg->prompt) 2781 prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 2782 arg->argv[arg->argn-1]); 2783 else 2784 log_Printf(LogWARN, "%s command must have arguments\n", 2785 arg->argv[arg->argn] ); 2786 2787 return 0; 2788 } 2789 2790 const char * 2791 command_ShowNegval(unsigned val) 2792 { 2793 switch (val&3) { 2794 case 1: return "disabled & accepted"; 2795 case 2: return "enabled & denied"; 2796 case 3: return "enabled & accepted"; 2797 } 2798 return "disabled & denied"; 2799 } 2800 2801 static int 2802 ClearCommand(struct cmdargs const *arg) 2803 { 2804 struct pppThroughput *t; 2805 struct datalink *cx; 2806 int i, clear_type; 2807 2808 if (arg->argc < arg->argn + 1) 2809 return -1; 2810 2811 if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 2812 cx = arg->cx; 2813 if (!cx) 2814 cx = bundle2datalink(arg->bundle, NULL); 2815 if (!cx) { 2816 log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 2817 return 1; 2818 } 2819 t = &cx->physical->link.stats.total; 2820 } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 2821 t = &arg->bundle->ncp.ipcp.throughput; 2822 else 2823 return -1; 2824 2825 if (arg->argc > arg->argn + 1) { 2826 clear_type = 0; 2827 for (i = arg->argn + 1; i < arg->argc; i++) 2828 if (strcasecmp(arg->argv[i], "overall") == 0) 2829 clear_type |= THROUGHPUT_OVERALL; 2830 else if (strcasecmp(arg->argv[i], "current") == 0) 2831 clear_type |= THROUGHPUT_CURRENT; 2832 else if (strcasecmp(arg->argv[i], "peak") == 0) 2833 clear_type |= THROUGHPUT_PEAK; 2834 else 2835 return -1; 2836 } else 2837 clear_type = THROUGHPUT_ALL; 2838 2839 throughput_clear(t, clear_type, arg->prompt); 2840 return 0; 2841 } 2842 2843 static int 2844 RunListCommand(struct cmdargs const *arg) 2845 { 2846 const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 2847 2848 #ifndef NONAT 2849 if (arg->cmd->args == NatCommands && 2850 tolower(*arg->argv[arg->argn - 1]) == 'a') { 2851 if (arg->prompt) 2852 prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 2853 else 2854 log_Printf(LogWARN, "The alias command is deprecated\n"); 2855 } 2856 #endif 2857 2858 if (arg->argc > arg->argn) 2859 FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 2860 arg->prompt, arg->cx); 2861 else if (arg->prompt) 2862 prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 2863 " <option>' for syntax help.\n", cmd, cmd); 2864 else 2865 log_Printf(LogWARN, "%s command must have arguments\n", cmd); 2866 2867 return 0; 2868 } 2869 2870 static int 2871 IfaceAddCommand(struct cmdargs const *arg) 2872 { 2873 int bits, n, how; 2874 struct in_addr ifa, mask, brd; 2875 2876 if (arg->argc == arg->argn + 1) { 2877 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 2878 return -1; 2879 mask.s_addr = brd.s_addr = INADDR_BROADCAST; 2880 } else { 2881 if (arg->argc == arg->argn + 2) { 2882 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 2883 return -1; 2884 n = 1; 2885 } else if (arg->argc == arg->argn + 3) { 2886 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 2887 return -1; 2888 if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 2889 return -1; 2890 n = 2; 2891 } else 2892 return -1; 2893 2894 if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 2895 return -1; 2896 } 2897 2898 how = IFACE_ADD_LAST; 2899 if (arg->cmd->args) 2900 how |= IFACE_FORCE_ADD; 2901 2902 return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 2903 } 2904 2905 static int 2906 IfaceDeleteCommand(struct cmdargs const *arg) 2907 { 2908 struct in_addr ifa; 2909 int ok; 2910 2911 if (arg->argc != arg->argn + 1) 2912 return -1; 2913 2914 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 2915 return -1; 2916 2917 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 2918 arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 2919 log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 2920 inet_ntoa(ifa)); 2921 return 1; 2922 } 2923 2924 ok = iface_inDelete(arg->bundle->iface, ifa); 2925 if (!ok) { 2926 if (arg->cmd->args) 2927 ok = 1; 2928 else if (arg->prompt) 2929 prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 2930 else 2931 log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 2932 } 2933 2934 return !ok; 2935 } 2936 2937 static int 2938 IfaceClearCommand(struct cmdargs const *arg) 2939 { 2940 int how; 2941 2942 if (arg->argc != arg->argn) 2943 return -1; 2944 2945 how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 2946 arg->bundle->phys_type.all & PHYS_AUTO ? 2947 IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 2948 iface_Clear(arg->bundle->iface, how); 2949 2950 return 0; 2951 } 2952 2953 static int 2954 SetProcTitle(struct cmdargs const *arg) 2955 { 2956 static char title[LINE_LEN]; 2957 char *argv[MAXARGS], *ptr; 2958 int len, remaining, f, argc = arg->argc - arg->argn; 2959 2960 if (arg->argc == arg->argn) { 2961 SetTitle(NULL); 2962 return 0; 2963 } 2964 2965 if (argc >= sizeof argv / sizeof argv[0]) { 2966 argc = sizeof argv / sizeof argv[0] - 1; 2967 log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 2968 } 2969 command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 2970 2971 ptr = title; 2972 remaining = sizeof title - 1; 2973 for (f = 0; f < argc && remaining; f++) { 2974 if (f) { 2975 *ptr++ = ' '; 2976 remaining--; 2977 } 2978 len = strlen(argv[f]); 2979 if (len > remaining) 2980 len = remaining; 2981 memcpy(ptr, argv[f], len); 2982 remaining -= len; 2983 ptr += len; 2984 } 2985 *ptr = '\0'; 2986 2987 SetTitle(title); 2988 2989 return 0; 2990 } 2991