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