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)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
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>
69 #include "throughput.h"
70 #include "slcompress.h"
81 #include "descriptor.h"
101 #include "datalink.h"
107 #define VAR_AUTHKEY 0
110 #define VAR_AUTHNAME 3
111 #define VAR_AUTOLOAD 4
112 #define VAR_WINSIZE 5
118 #define VAR_OPENMODE 11
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
131 #define VAR_CALLBACK 24
133 #define VAR_CHOKED 26
134 #define VAR_SENDPIPE 27
135 #define VAR_RECVPIPE 28
136 #define VAR_RADIUS 29
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
144 #define VAR_IPV6CPRETRY 37
145 #define VAR_RAD_ALIVE 38
147 #define VAR_PORT_ID 40
149 /* ``accept|deny|disable|enable'' masks */
150 #define NEG_HISMASK (1)
151 #define NEG_MYMASK (2)
153 /* ``accept|deny|disable|enable'' values */
154 #define NEG_ACFCOMP 40
155 #define NEG_CHAP05 41
156 #define NEG_CHAP80 42
157 #define NEG_CHAP80LM 43
158 #define NEG_DEFLATE 44
161 #define NEG_ENDDISC 47
164 #define NEG_PPPDDEFLATE 50
166 #define NEG_PROTOCOMP 52
167 #define NEG_SHORTSEQ 53
168 #define NEG_VJCOMP 54
170 #define NEG_CHAP81 56
172 const char Version[] = "3.4.2";
174 static int ShowCommand(struct cmdargs const *);
175 static int TerminalCommand(struct cmdargs const *);
176 static int QuitCommand(struct cmdargs const *);
177 static int OpenCommand(struct cmdargs const *);
178 static int CloseCommand(struct cmdargs const *);
179 static int DownCommand(struct cmdargs const *);
180 static int SetCommand(struct cmdargs const *);
181 static int LinkCommand(struct cmdargs const *);
182 static int AddCommand(struct cmdargs const *);
183 static int DeleteCommand(struct cmdargs const *);
184 static int NegotiateCommand(struct cmdargs const *);
185 static int ClearCommand(struct cmdargs const *);
186 static int RunListCommand(struct cmdargs const *);
187 static int IfaceAddCommand(struct cmdargs const *);
188 static int IfaceDeleteCommand(struct cmdargs const *);
189 static int IfaceClearCommand(struct cmdargs const *);
190 static int SetProcTitle(struct cmdargs const *);
192 static int NatEnable(struct cmdargs const *);
193 static int NatOption(struct cmdargs const *);
196 extern struct libalias *la;
199 showcx(struct cmdtab const *cmd)
201 if (cmd->lauth & LOCAL_CX)
203 else if (cmd->lauth & LOCAL_CX_OPT)
210 HelpCommand(struct cmdargs const *arg)
212 struct cmdtab const *cmd;
213 int n, cmax, dmax, cols, cxlen;
217 log_Printf(LogWARN, "help: Cannot help without a prompt\n");
221 if (arg->argc > arg->argn) {
222 for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++)
223 if ((cmd->lauth & arg->prompt->auth) &&
224 ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) ||
225 (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) {
226 prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd));
233 for (cmd = arg->cmdtab; cmd->func; cmd++)
234 if (cmd->name && (cmd->lauth & arg->prompt->auth)) {
235 if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax)
237 if ((n = strlen(cmd->helpmes)) > dmax)
241 cols = 80 / (dmax + cmax + 3);
243 prompt_Printf(arg->prompt, "(o) = Optional context,"
244 " (c) = Context required\n");
245 for (cmd = arg->cmdtab; cmd->func; cmd++)
246 if (cmd->name && (cmd->lauth & arg->prompt->auth)) {
248 cxlen = cmax - strlen(cmd->name);
250 prompt_Printf(arg->prompt, " ");
251 prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s",
252 cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes);
254 prompt_Printf(arg->prompt, "\n");
257 prompt_Printf(arg->prompt, "\n");
263 IdentCommand(struct cmdargs const *arg)
265 Concatinate(arg->cx->physical->link.lcp.cfg.ident,
266 sizeof arg->cx->physical->link.lcp.cfg.ident,
267 arg->argc - arg->argn, arg->argv + arg->argn);
272 SendIdentification(struct cmdargs const *arg)
274 if (arg->cx->state < DATALINK_LCP) {
275 log_Printf(LogWARN, "sendident: link has not reached LCP\n");
278 return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1;
282 CloneCommand(struct cmdargs const *arg)
284 char namelist[LINE_LEN];
288 if (arg->argc == arg->argn)
291 namelist[sizeof namelist - 1] = '\0';
292 for (f = arg->argn; f < arg->argc; f++) {
293 strncpy(namelist, arg->argv[f], sizeof namelist - 1);
294 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", "))
295 bundle_DatalinkClone(arg->bundle, arg->cx, name);
302 RemoveCommand(struct cmdargs const *arg)
304 if (arg->argc != arg->argn)
307 if (arg->cx->state != DATALINK_CLOSED) {
308 log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n");
312 bundle_DatalinkRemove(arg->bundle, arg->cx);
317 RenameCommand(struct cmdargs const *arg)
319 if (arg->argc != arg->argn + 1)
322 if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn]))
325 log_Printf(LogWARN, "%s -> %s: target name already exists\n",
326 arg->cx->name, arg->argv[arg->argn]);
331 LoadCommand(struct cmdargs const *arg)
336 mode = arg->bundle->phys_type.all;
338 if (arg->argn < arg->argc) {
339 for (n = arg->argn; n < arg->argc; n++)
340 if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) {
341 log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err);
345 for (n = arg->argn; n < arg->argc; n++) {
346 bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]);
347 system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx);
349 bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]);
350 } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) {
351 log_Printf(LogWARN, "default: %s\n", err);
354 bundle_SetLabel(arg->bundle, "default");
355 system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx);
356 bundle_SetLabel(arg->bundle, "default");
363 LogCommand(struct cmdargs const *arg)
367 if (arg->argn < arg->argc) {
369 int argc = arg->argc - arg->argn;
371 if (argc >= (int)(sizeof argv / sizeof argv[0])) {
372 argc = sizeof argv / sizeof argv[0] - 1;
373 log_Printf(LogWARN, "Truncating log command to %d args\n", argc);
375 command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid());
376 Concatinate(buf, sizeof buf, argc, (const char *const *)argv);
377 log_Printf(LogLOG, "%s\n", buf);
378 command_Free(argc, argv);
386 SaveCommand(struct cmdargs const *arg __unused)
388 log_Printf(LogWARN, "save command is not yet implemented.\n");
393 DialCommand(struct cmdargs const *arg)
397 if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO)))
399 (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) {
400 log_Printf(LogWARN, "Manual dial is only available for auto and"
401 " interactive links\n");
405 if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0)
408 bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1);
413 #define isinword(ch) (isalnum(ch) || (ch) == '_')
416 strstrword(char *big, const char *little)
418 /* Get the first occurance of the word ``little'' in ``big'' */
423 len = strlen(little);
425 while ((pos = strstr(pos, little)) != NULL)
426 if ((pos != big && isinword(pos[-1])) || isinword(pos[len]))
428 else if (pos != big && pos[-1] == '\\')
429 memmove(pos - 1, pos, strlen(pos) + 1);
437 subst(char *tgt, const char *oldstr, const char *newstr)
439 /* tgt is a malloc()d area... realloc() as necessary */
441 int ltgt, loldstr, lnewstr, pos;
443 if ((word = strstrword(tgt, oldstr)) == NULL)
446 ltgt = strlen(tgt) + 1;
447 loldstr = strlen(oldstr);
448 lnewstr = strlen(newstr);
451 if (loldstr > lnewstr)
452 bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr);
453 if (loldstr != lnewstr) {
454 ntgt = realloc(tgt, ltgt += lnewstr - loldstr);
456 break; /* Oh wonderful ! */
460 if (lnewstr > loldstr)
461 bcopy(word + loldstr, word + lnewstr, ltgt - pos - lnewstr);
462 bcopy(newstr, word, lnewstr);
463 } while ((word = strstrword(word, oldstr)));
469 substip(char *tgt, const char *oldstr, struct in_addr ip)
471 return subst(tgt, oldstr, inet_ntoa(ip));
475 substlong(char *tgt, const char *oldstr, long l)
479 snprintf(buf, sizeof buf, "%ld", l);
481 return subst(tgt, oldstr, buf);
485 substull(char *tgt, const char *oldstr, unsigned long long ull)
489 snprintf(buf, sizeof buf, "%llu", ull);
491 return subst(tgt, oldstr, buf);
497 substipv6(char *tgt, const char *oldstr, const struct ncpaddr *ip)
499 return subst(tgt, oldstr, ncpaddr_ntoa(ip));
504 substipv6prefix(char *tgt, const char *oldstr, const uint8_t *ipv6prefix)
506 uint8_t ipv6addr[INET6_ADDRSTRLEN];
507 uint8_t prefix[INET6_ADDRSTRLEN + sizeof("/128") - 1];
510 inet_ntop(AF_INET6, &ipv6prefix[2], ipv6addr, sizeof(ipv6addr));
511 snprintf(prefix, sizeof(prefix), "%s/%d", ipv6addr, ipv6prefix[1]);
514 return subst(tgt, oldstr, prefix);
520 command_Expand(char **nargv, int argc, char const *const *oargv,
521 struct bundle *bundle, int inc0, pid_t pid)
525 unsigned long long oin, oout, pin, pout;
528 arg = 0; /* Start at arg 0 */
530 nargv[0] = strdup(oargv[0]);
534 secs = bundle_Uptime(bundle);
535 snprintf(uptime, sizeof uptime, "%d:%02d:%02d",
536 secs / 3600, (secs / 60) % 60, secs % 60);
537 oin = bundle->ncp.ipcp.throughput.OctetsIn;
538 oout = bundle->ncp.ipcp.throughput.OctetsOut;
539 pin = bundle->ncp.ipcp.throughput.PacketsIn;
540 pout = bundle->ncp.ipcp.throughput.PacketsOut;
542 oin += bundle->ncp.ipv6cp.throughput.OctetsIn;
543 oout += bundle->ncp.ipv6cp.throughput.OctetsOut;
544 pin += bundle->ncp.ipv6cp.throughput.PacketsIn;
545 pout += bundle->ncp.ipv6cp.throughput.PacketsOut;
548 for (; arg < argc; arg++) {
549 nargv[arg] = strdup(oargv[arg]);
550 nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name);
551 nargv[arg] = substip(nargv[arg], "DNS0", bundle->ncp.ipcp.ns.dns[0]);
552 nargv[arg] = substip(nargv[arg], "DNS1", bundle->ncp.ipcp.ns.dns[1]);
553 nargv[arg] = subst(nargv[arg], "ENDDISC",
554 mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class,
555 bundle->ncp.mp.cfg.enddisc.address,
556 bundle->ncp.mp.cfg.enddisc.len));
557 nargv[arg] = substip(nargv[arg], "HISADDR", bundle->ncp.ipcp.peer_ip);
559 nargv[arg] = substipv6(nargv[arg], "HISADDR6", &bundle->ncp.ipv6cp.hisaddr);
561 nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name);
562 nargv[arg] = substull(nargv[arg], "IPOCTETSIN",
563 bundle->ncp.ipcp.throughput.OctetsIn);
564 nargv[arg] = substull(nargv[arg], "IPOCTETSOUT",
565 bundle->ncp.ipcp.throughput.OctetsOut);
566 nargv[arg] = substull(nargv[arg], "IPPACKETSIN",
567 bundle->ncp.ipcp.throughput.PacketsIn);
568 nargv[arg] = substull(nargv[arg], "IPPACKETSOUT",
569 bundle->ncp.ipcp.throughput.PacketsOut);
571 nargv[arg] = substull(nargv[arg], "IPV6OCTETSIN",
572 bundle->ncp.ipv6cp.throughput.OctetsIn);
573 nargv[arg] = substull(nargv[arg], "IPV6OCTETSOUT",
574 bundle->ncp.ipv6cp.throughput.OctetsOut);
575 nargv[arg] = substull(nargv[arg], "IPV6PACKETSIN",
576 bundle->ncp.ipv6cp.throughput.PacketsIn);
577 nargv[arg] = substull(nargv[arg], "IPV6PACKETSOUT",
578 bundle->ncp.ipv6cp.throughput.PacketsOut);
580 nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle));
581 nargv[arg] = substip(nargv[arg], "MYADDR", bundle->ncp.ipcp.my_ip);
583 nargv[arg] = substipv6(nargv[arg], "MYADDR6", &bundle->ncp.ipv6cp.myaddr);
585 nargv[arg] = substipv6prefix(nargv[arg], "IPV6PREFIX",
586 bundle->radius.ipv6prefix);
589 nargv[arg] = substull(nargv[arg], "OCTETSIN", oin);
590 nargv[arg] = substull(nargv[arg], "OCTETSOUT", oout);
591 nargv[arg] = substull(nargv[arg], "PACKETSIN", pin);
592 nargv[arg] = substull(nargv[arg], "PACKETSOUT", pout);
593 nargv[arg] = subst(nargv[arg], "PEER_ENDDISC",
594 mp_Enddisc(bundle->ncp.mp.peer.enddisc.class,
595 bundle->ncp.mp.peer.enddisc.address,
596 bundle->ncp.mp.peer.enddisc.len));
597 nargv[arg] = substlong(nargv[arg], "PROCESSID", pid);
599 nargv[arg] = substlong(nargv[arg], "SOCKNAME", server.cfg.port);
601 nargv[arg] = subst(nargv[arg], "SOCKNAME", server.cfg.sockname);
602 nargv[arg] = subst(nargv[arg], "UPTIME", uptime);
603 nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname);
604 nargv[arg] = subst(nargv[arg], "VERSION", Version);
610 command_Free(int argc, char **argv)
620 ShellCommand(struct cmdargs const *arg, int bg)
625 #ifdef SHELL_ONLY_INTERACTIVELY
626 /* we're only allowed to shell when we run ppp interactively */
627 if (arg->prompt && arg->prompt->owner) {
628 log_Printf(LogWARN, "Can't start a shell from a network connection\n");
633 if (arg->argc == arg->argn) {
635 log_Printf(LogWARN, "Can't start an interactive shell from"
638 } else if (arg->prompt->owner) {
639 log_Printf(LogWARN, "Can't start an interactive shell from"
640 " a socket connection\n");
643 log_Printf(LogWARN, "Can only start an interactive shell in"
644 " the foreground mode\n");
650 if ((shpid = fork()) == 0) {
653 if ((shell = getenv("SHELL")) == 0)
654 shell = _PATH_BSHELL;
659 fd = arg->prompt->fd_out;
660 else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
661 log_Printf(LogALERT, "Failed to open %s: %s\n",
662 _PATH_DEVNULL, strerror(errno));
665 dup2(fd, STDIN_FILENO);
666 dup2(fd, STDOUT_FILENO);
667 dup2(fd, STDERR_FILENO);
668 for (i = getdtablesize(); i > STDERR_FILENO; i--)
669 fcntl(i, F_SETFD, 1);
672 setuid(ID0realuid());
674 if (arg->argc > arg->argn) {
675 /* substitute pseudo args */
677 int argc = arg->argc - arg->argn;
679 if (argc >= (int)(sizeof argv / sizeof argv[0])) {
680 argc = sizeof argv / sizeof argv[0] - 1;
681 log_Printf(LogWARN, "Truncating shell command to %d args\n", argc);
683 command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid);
688 if (daemon(1, 1) == -1) {
689 log_Printf(LogERROR, "%ld: daemon: %s\n", (long)p, strerror(errno));
692 } else if (arg->prompt)
693 printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]);
694 execvp(argv[0], argv);
697 printf("ppp: Pausing until %s finishes\n", shell);
698 prompt_TtyOldMode(arg->prompt);
699 execl(shell, shell, (char *)NULL);
702 log_Printf(LogWARN, "exec() of %s failed: %s\n",
703 arg->argc > arg->argn ? arg->argv[arg->argn] : shell,
708 if (shpid == (pid_t)-1)
709 log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno));
712 waitpid(shpid, &status, 0);
715 if (arg->prompt && !arg->prompt->owner)
716 prompt_TtyCommandMode(arg->prompt);
722 BgShellCommand(struct cmdargs const *arg)
724 if (arg->argc == arg->argn)
726 return ShellCommand(arg, 1);
730 FgShellCommand(struct cmdargs const *arg)
732 return ShellCommand(arg, 0);
736 ResolvCommand(struct cmdargs const *arg)
738 if (arg->argc == arg->argn + 1) {
739 if (!strcasecmp(arg->argv[arg->argn], "reload"))
740 ipcp_LoadDNS(&arg->bundle->ncp.ipcp);
741 else if (!strcasecmp(arg->argv[arg->argn], "restore"))
742 ipcp_RestoreDNS(&arg->bundle->ncp.ipcp);
743 else if (!strcasecmp(arg->argv[arg->argn], "rewrite"))
744 ipcp_WriteDNS(&arg->bundle->ncp.ipcp);
745 else if (!strcasecmp(arg->argv[arg->argn], "readonly"))
746 arg->bundle->ncp.ipcp.ns.writable = 0;
747 else if (!strcasecmp(arg->argv[arg->argn], "writable"))
748 arg->bundle->ncp.ipcp.ns.writable = 1;
759 static struct cmdtab const NatCommands[] =
761 {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH,
762 "static address translation", "nat addr [addr_local addr_alias]", NULL},
763 {"deny_incoming", NULL, NatOption, LOCAL_AUTH,
764 "stop incoming connections", "nat deny_incoming yes|no",
765 (const void *) PKT_ALIAS_DENY_INCOMING},
766 {"enable", NULL, NatEnable, LOCAL_AUTH,
767 "enable NAT", "nat enable yes|no", NULL},
768 {"log", NULL, NatOption, LOCAL_AUTH,
769 "log NAT link creation", "nat log yes|no",
770 (const void *) PKT_ALIAS_LOG},
771 {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection",
772 "nat port proto localaddr:port[-port] aliasport[-aliasport]", NULL},
773 {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection",
774 "nat proto proto localIP [publicIP [remoteIP]]", NULL},
775 {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH,
776 "proxy control", "nat proxy server host[:port] ...", NULL},
778 {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH,
779 "firewall control", "nat punch_fw [base count]", NULL},
781 {"skinny_port", NULL, nat_SkinnyPort, LOCAL_AUTH,
782 "TCP port used by Skinny Station protocol", "nat skinny_port [port]", NULL},
783 {"same_ports", NULL, NatOption, LOCAL_AUTH,
784 "try to leave port numbers unchanged", "nat same_ports yes|no",
785 (const void *) PKT_ALIAS_SAME_PORTS},
786 {"target", NULL, nat_SetTarget, LOCAL_AUTH,
787 "Default address for incoming connections", "nat target addr", NULL},
788 {"unregistered_only", NULL, NatOption, LOCAL_AUTH,
789 "translate unregistered (private) IP address space only",
790 "nat unregistered_only yes|no",
791 (const void *) PKT_ALIAS_UNREGISTERED_ONLY},
792 {"use_sockets", NULL, NatOption, LOCAL_AUTH,
793 "allocate host sockets", "nat use_sockets yes|no",
794 (const void *) PKT_ALIAS_USE_SOCKETS},
795 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
796 "Display this message", "nat help|? [command]", NatCommands},
797 {NULL, NULL, NULL, 0, NULL, NULL, NULL},
801 static struct cmdtab const AllowCommands[] = {
802 {"modes", "mode", AllowModes, LOCAL_AUTH,
803 "Only allow certain ppp modes", "allow modes mode...", NULL},
804 {"users", "user", AllowUsers, LOCAL_AUTH,
805 "Only allow ppp access to certain users", "allow users logname...", NULL},
806 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
807 "Display this message", "allow help|? [command]", AllowCommands},
808 {NULL, NULL, NULL, 0, NULL, NULL, NULL},
811 static struct cmdtab const IfaceCommands[] =
813 {"add", NULL, IfaceAddCommand, LOCAL_AUTH,
814 "Add iface address", "iface add addr[/bits| mask] peer", NULL},
815 {NULL, "add!", IfaceAddCommand, LOCAL_AUTH,
816 "Add or change an iface address", "iface add! addr[/bits| mask] peer",
818 {"clear", NULL, IfaceClearCommand, LOCAL_AUTH,
819 "Clear iface address(es)", "iface clear [INET | INET6]", NULL},
820 {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH,
821 "Delete iface address", "iface delete addr", NULL},
822 {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH,
823 "Delete iface address", "iface delete addr", (void *)1},
824 {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH,
825 "Delete iface address", "iface delete addr", (void *)1},
826 {"show", NULL, iface_Show, LOCAL_AUTH,
827 "Show iface address(es)", "iface show", NULL},
828 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
829 "Display this message", "nat help|? [command]", IfaceCommands},
830 {NULL, NULL, NULL, 0, NULL, NULL, NULL},
833 static struct cmdtab const Commands[] = {
834 {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
835 "accept option request", "accept option ..", NULL},
836 {"add", NULL, AddCommand, LOCAL_AUTH,
837 "add route", "add dest mask gateway", NULL},
838 {NULL, "add!", AddCommand, LOCAL_AUTH,
839 "add or change route", "add! dest mask gateway", (void *)1},
840 {"allow", "auth", RunListCommand, LOCAL_AUTH,
841 "Allow ppp access", "allow users|modes ....", AllowCommands},
842 {"bg", "!bg", BgShellCommand, LOCAL_AUTH,
843 "Run a background command", "[!]bg command", NULL},
844 {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT,
845 "Clear throughput statistics",
846 "clear ipcp|ipv6cp|physical [current|overall|peak]...", NULL},
847 {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX,
848 "Clone a link", "clone newname...", NULL},
849 {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT,
850 "Close an FSM", "close [lcp|ccp]", NULL},
851 {"delete", NULL, DeleteCommand, LOCAL_AUTH,
852 "delete route", "delete dest", NULL},
853 {NULL, "delete!", DeleteCommand, LOCAL_AUTH,
854 "delete a route if it exists", "delete! dest", (void *)1},
855 {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
856 "Deny option request", "deny option ..", NULL},
857 {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT,
858 "Dial and login", "dial|call [system ...]", NULL},
859 {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
860 "Disable option", "disable option ..", NULL},
861 {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT,
862 "Generate a down event", "down [ccp|lcp]", NULL},
863 {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
864 "Enable option", "enable option ..", NULL},
865 {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX,
866 "Set the link identity", "ident text...", NULL},
867 {"iface", "interface", RunListCommand, LOCAL_AUTH,
868 "interface control", "iface option ...", IfaceCommands},
869 {"link", "datalink", LinkCommand, LOCAL_AUTH,
870 "Link specific commands", "link name command ...", NULL},
871 {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT,
872 "Load settings", "load [system ...]", NULL},
873 {"log", NULL, LogCommand, LOCAL_AUTH | LOCAL_CX_OPT,
874 "log information", "log word ...", NULL},
876 {"nat", "alias", RunListCommand, LOCAL_AUTH,
877 "NAT control", "nat option yes|no", NatCommands},
879 {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT,
880 "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1},
881 {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH,
882 "Password for manipulation", "passwd LocalPassword", NULL},
883 {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
884 "Quit PPP program", "quit|bye [all]", NULL},
885 {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX,
886 "Remove a link", "remove", NULL},
887 {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX,
888 "Rename a link", "rename name", NULL},
889 {"resolv", NULL, ResolvCommand, LOCAL_AUTH,
890 "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable",
892 {"save", NULL, SaveCommand, LOCAL_AUTH,
893 "Save settings", "save", NULL},
894 {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX,
895 "Transmit the link identity", "sendident", NULL},
896 {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT,
897 "Set parameters", "set[up] var value", NULL},
898 {"shell", "!", FgShellCommand, LOCAL_AUTH,
899 "Run a subshell", "shell|! [sh command]", NULL},
900 {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT,
901 "Show status and stats", "show var", NULL},
902 {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX,
903 "Enter terminal mode", "term", NULL},
904 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
905 "Display this message", "help|? [command]", Commands},
906 {NULL, NULL, NULL, 0, NULL, NULL, NULL},
910 ShowEscape(struct cmdargs const *arg)
912 if (arg->cx->physical->async.cfg.EscMap[32]) {
914 const char *sep = "";
916 for (code = 0; code < 32; code++)
917 if (arg->cx->physical->async.cfg.EscMap[code])
918 for (bit = 0; bit < 8; bit++)
919 if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) {
920 prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit);
923 prompt_Printf(arg->prompt, "\n");
929 ShowTimerList(struct cmdargs const *arg)
931 timer_Show(0, arg->prompt);
936 ShowStopped(struct cmdargs const *arg)
938 prompt_Printf(arg->prompt, " Stopped Timer: LCP: ");
939 if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load)
940 prompt_Printf(arg->prompt, "Disabled");
942 prompt_Printf(arg->prompt, "%ld secs",
943 arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS);
945 prompt_Printf(arg->prompt, ", CCP: ");
946 if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load)
947 prompt_Printf(arg->prompt, "Disabled");
949 prompt_Printf(arg->prompt, "%ld secs",
950 arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS);
952 prompt_Printf(arg->prompt, "\n");
958 ShowVersion(struct cmdargs const *arg)
960 prompt_Printf(arg->prompt, "PPP Version %s\n", Version);
965 ShowProtocolStats(struct cmdargs const *arg)
967 struct link *l = command_ChooseLink(arg);
969 prompt_Printf(arg->prompt, "%s:\n", l->name);
970 link_ReportProtocolStatus(l, arg->prompt);
974 static struct cmdtab const ShowCommands[] = {
975 {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH,
976 "bundle details", "show bundle", NULL},
977 {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT,
978 "CCP status", "show cpp", NULL},
979 {"compress", NULL, sl_Show, LOCAL_AUTH,
980 "VJ compression stats", "show compress", NULL},
981 {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX,
982 "escape characters", "show escape", NULL},
983 {"filter", NULL, filter_Show, LOCAL_AUTH,
984 "packet filters", "show filter [in|out|dial|alive]", NULL},
985 {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX,
986 "HDLC errors", "show hdlc", NULL},
987 {"iface", "interface", iface_Show, LOCAL_AUTH,
988 "Interface status", "show iface", NULL},
989 {"ipcp", NULL, ipcp_Show, LOCAL_AUTH,
990 "IPCP status", "show ipcp", NULL},
992 {"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH,
993 "IPV6CP status", "show ipv6cp", NULL},
995 {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT,
996 "Protocol layers", "show layers", NULL},
997 {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX,
998 "LCP status", "show lcp", NULL},
999 {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX,
1000 "(high-level) link info", "show link", NULL},
1001 {"links", NULL, bundle_ShowLinks, LOCAL_AUTH,
1002 "available link names", "show links", NULL},
1003 {"log", NULL, log_ShowLevel, LOCAL_AUTH,
1004 "log levels", "show log", NULL},
1005 {"mem", NULL, mbuf_Show, LOCAL_AUTH,
1006 "mbuf allocations", "show mem", NULL},
1007 {"ncp", NULL, ncp_Show, LOCAL_AUTH,
1008 "NCP status", "show ncp", NULL},
1009 {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX,
1010 "(low-level) link info", "show physical", NULL},
1011 {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH,
1012 "multilink setup", "show mp", NULL},
1013 {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT,
1014 "protocol summary", "show proto", NULL},
1015 {"route", NULL, route_Show, LOCAL_AUTH,
1016 "routing table", "show route", NULL},
1017 {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX,
1018 "STOPPED timeout", "show stopped", NULL},
1019 {"timers", NULL, ShowTimerList, LOCAL_AUTH,
1020 "alarm timers", "show timers", NULL},
1021 {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
1022 "version string", "show version", NULL},
1023 {"who", NULL, log_ShowWho, LOCAL_AUTH,
1024 "client list", "show who", NULL},
1025 {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
1026 "Display this message", "show help|? [command]", ShowCommands},
1027 {NULL, NULL, NULL, 0, NULL, NULL, NULL},
1030 static struct cmdtab const *
1031 FindCommand(struct cmdtab const *cmds, const char *str, int *pmatch)
1035 struct cmdtab const *found;
1040 while (cmds->func) {
1041 if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
1042 if (cmds->name[len] == '\0') {
1048 } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
1049 if (cmds->alias[len] == '\0') {
1063 mkPrefix(int argc, char const *const *argv, char *tgt, int sz)
1068 for (f = 0; f < argc && tlen < sz - 2; f++) {
1071 len = strlen(argv[f]);
1072 if (len > sz - tlen - 1)
1073 len = sz - tlen - 1;
1074 strncpy(tgt+tlen, argv[f], len);
1082 FindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn,
1083 char const *const *argv, struct prompt *prompt, struct datalink *cx)
1085 struct cmdtab const *cmd;
1091 cmd = FindCommand(cmds, argv[argn], &nmatch);
1093 log_Printf(LogWARN, "%s: Ambiguous command\n",
1094 mkPrefix(argn+1, argv, prefix, sizeof prefix));
1095 else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) {
1096 if ((cmd->lauth & LOCAL_CX) && !cx)
1097 /* We've got no context, but we require it */
1098 cx = bundle2datalink(bundle, NULL);
1100 if ((cmd->lauth & LOCAL_CX) && !cx)
1101 log_Printf(LogWARN, "%s: No context (use the `link' command)\n",
1102 mkPrefix(argn+1, argv, prefix, sizeof prefix));
1104 if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) {
1105 log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n",
1106 mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name);
1114 arg.bundle = bundle;
1116 arg.prompt = prompt;
1117 val = (*cmd->func) (&arg);
1120 log_Printf(LogWARN, "%s: Invalid command\n",
1121 mkPrefix(argn+1, argv, prefix, sizeof prefix));
1124 log_Printf(LogWARN, "usage: %s\n", cmd->syntax);
1126 log_Printf(LogWARN, "%s: Failed %d\n",
1127 mkPrefix(argn+1, argv, prefix, sizeof prefix), val);
1133 command_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset)
1135 char buff2[LINE_LEN-offset];
1137 InterpretArg(buff, buff2);
1138 strncpy(buff, buff2, LINE_LEN - offset - 1);
1139 buff[LINE_LEN - offset - 1] = '\0';
1141 return command_Interpret(buff, nb, argv);
1145 command_Interpret(char *buff, int nb, char *argv[MAXARGS])
1150 cp = buff + strcspn(buff, "\r\n");
1153 return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE);
1159 arghidden(char const *const *argv, int n)
1161 /* Is arg n of the given command to be hidden from the log ? */
1163 /* set authkey xxxxx */
1165 if (n == 2 && !strncasecmp(argv[0], "se", 2) &&
1166 (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2)))
1170 if (n == 1 && !strncasecmp(argv[0], "p", 1))
1173 /* set server port xxxxx .... */
1174 if (n == 3 && !strncasecmp(argv[0], "se", 2) &&
1175 !strncasecmp(argv[1], "se", 2))
1182 command_Run(struct bundle *bundle, int argc, char const *const *argv,
1183 struct prompt *prompt, const char *label, struct datalink *cx)
1186 if (log_IsKept(LogCOMMAND)) {
1192 strncpy(buf, label, sizeof buf - 3);
1193 buf[sizeof buf - 3] = '\0';
1200 buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */
1202 for (f = 0; f < argc; f++) {
1203 if (n < sizeof buf - 1 && f)
1205 if (arghidden(argv, f))
1206 strncpy(buf+n, "********", sizeof buf - n - 1);
1208 strncpy(buf+n, argv[f], sizeof buf - n - 1);
1211 log_Printf(LogCOMMAND, "%s\n", buf);
1213 FindExec(bundle, Commands, argc, 0, argv, prompt, cx);
1218 command_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt,
1222 char *argv[MAXARGS];
1224 if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0)
1227 command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL);
1232 ShowCommand(struct cmdargs const *arg)
1235 log_Printf(LogWARN, "show: Cannot show without a prompt\n");
1236 else if (arg->argc > arg->argn)
1237 FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv,
1238 arg->prompt, arg->cx);
1240 prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n");
1246 TerminalCommand(struct cmdargs const *arg)
1249 log_Printf(LogWARN, "term: Need a prompt\n");
1253 if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) {
1254 prompt_Printf(arg->prompt, "LCP state is [%s]\n",
1255 State2Nam(arg->cx->physical->link.lcp.fsm.state));
1259 datalink_Up(arg->cx, 0, 0);
1260 prompt_TtyTermMode(arg->prompt, arg->cx);
1265 QuitCommand(struct cmdargs const *arg)
1267 if (!arg->prompt || prompt_IsController(arg->prompt) ||
1268 (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") &&
1269 (arg->prompt->auth & LOCAL_AUTH)))
1272 prompt_Destroy(arg->prompt, 1);
1278 OpenCommand(struct cmdargs const *arg)
1280 if (arg->argc == arg->argn)
1281 bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1);
1282 else if (arg->argc == arg->argn + 1) {
1283 if (!strcasecmp(arg->argv[arg->argn], "lcp")) {
1284 struct datalink *cx = arg->cx ?
1285 arg->cx : bundle2datalink(arg->bundle, NULL);
1287 if (cx->physical->link.lcp.fsm.state == ST_OPENED)
1288 fsm_Reopen(&cx->physical->link.lcp.fsm);
1290 bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1);
1292 log_Printf(LogWARN, "open lcp: You must specify a link\n");
1293 } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) {
1296 fp = &command_ChooseLink(arg)->ccp.fsm;
1297 if (fp->link->lcp.fsm.state != ST_OPENED)
1298 log_Printf(LogWARN, "open: LCP must be open before opening CCP\n");
1299 else if (fp->state == ST_OPENED)
1302 fp->open_mode = 0; /* Not passive any more */
1303 if (fp->state == ST_STOPPED) {
1311 } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) {
1313 log_Printf(LogWARN, "open ipcp: You need not specify a link\n");
1314 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED)
1315 fsm_Reopen(&arg->bundle->ncp.ipcp.fsm);
1317 bundle_Open(arg->bundle, NULL, PHYS_ALL, 1);
1327 CloseCommand(struct cmdargs const *arg)
1329 if (arg->argc == arg->argn)
1330 bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN);
1331 else if (arg->argc == arg->argn + 1) {
1332 if (!strcasecmp(arg->argv[arg->argn], "lcp"))
1333 bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP);
1334 else if (!strcasecmp(arg->argv[arg->argn], "ccp") ||
1335 !strcasecmp(arg->argv[arg->argn], "ccp!")) {
1338 fp = &command_ChooseLink(arg)->ccp.fsm;
1339 if (fp->state == ST_OPENED) {
1341 if (arg->argv[arg->argn][3] == '!')
1342 fp->open_mode = 0; /* Stay ST_CLOSED */
1344 fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */
1355 DownCommand(struct cmdargs const *arg)
1357 if (arg->argc == arg->argn) {
1359 datalink_Down(arg->cx, CLOSE_STAYDOWN);
1361 bundle_Down(arg->bundle, CLOSE_STAYDOWN);
1362 } else if (arg->argc == arg->argn + 1) {
1363 if (!strcasecmp(arg->argv[arg->argn], "lcp")) {
1365 datalink_Down(arg->cx, CLOSE_LCP);
1367 bundle_Down(arg->bundle, CLOSE_LCP);
1368 } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) {
1369 struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm :
1370 &arg->bundle->ncp.mp.link.ccp.fsm;
1381 SetModemSpeed(struct cmdargs const *arg)
1386 if (arg->argc > arg->argn && *arg->argv[arg->argn]) {
1387 if (arg->argc > arg->argn+1) {
1388 log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n");
1391 if (strcasecmp(arg->argv[arg->argn], "sync") == 0) {
1392 physical_SetSync(arg->cx->physical);
1396 speed = strtol(arg->argv[arg->argn], &end, 10);
1397 if (*end || speed < 0) {
1398 log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"",
1399 arg->argv[arg->argn]);
1402 if (physical_SetSpeed(arg->cx->physical, speed))
1404 log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]);
1406 log_Printf(LogWARN, "SetModemSpeed: No speed specified\n");
1412 SetStoppedTimeout(struct cmdargs const *arg)
1414 struct link *l = &arg->cx->physical->link;
1416 l->lcp.fsm.StoppedTimer.load = 0;
1417 l->ccp.fsm.StoppedTimer.load = 0;
1418 if (arg->argc <= arg->argn+2) {
1419 if (arg->argc > arg->argn) {
1420 l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS;
1421 if (arg->argc > arg->argn+1)
1422 l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS;
1430 SetServer(struct cmdargs const *arg)
1434 if (arg->argc > arg->argn && arg->argc < arg->argn+4) {
1435 const char *port, *passwd, *mask;
1439 port = arg->argv[arg->argn];
1440 if (arg->argc == arg->argn + 2) {
1441 passwd = arg->argv[arg->argn+1];
1443 } else if (arg->argc == arg->argn + 3) {
1444 passwd = arg->argv[arg->argn+1];
1445 mask = arg->argv[arg->argn+2];
1446 mlen = strlen(mask);
1447 if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen ||
1448 (mlen == 4 && *mask != '0')) {
1449 log_Printf(LogWARN, "%s %s: %s: Invalid mask\n",
1450 arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask);
1453 } else if (arg->argc != arg->argn + 1)
1455 else if (strcasecmp(port, "none") == 0) {
1456 if (server_Clear(arg->bundle))
1457 log_Printf(LogPHASE, "Disabled server socket\n");
1459 } else if (strcasecmp(port, "open") == 0) {
1460 switch (server_Reopen(arg->bundle)) {
1464 log_Printf(LogWARN, "Failed to reopen server port\n");
1467 log_Printf(LogWARN, "Cannot reopen unset server socket\n");
1473 } else if (strcasecmp(port, "closed") == 0) {
1474 if (server_Close(arg->bundle))
1475 log_Printf(LogPHASE, "Closed server socket\n");
1477 log_Printf(LogWARN, "Server socket not open\n");
1483 strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1);
1484 server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0';
1488 char *ptr, name[LINE_LEN + 12];
1492 else for (imask = mlen = 0; mask[mlen]; mlen++)
1493 imask = (imask * 8) + mask[mlen] - '0';
1495 ptr = strstr(port, "%d");
1497 snprintf(name, sizeof name, "%.*s%d%s",
1498 (int)(ptr - port), port, arg->bundle->unit, ptr + 2);
1501 res = server_LocalOpen(arg->bundle, port, imask);
1512 if (strspn(port, "0123456789") != strlen(port)) {
1515 if ((s = getservbyname(port, "tcp")) == NULL) {
1517 log_Printf(LogWARN, "%s: Invalid port or service\n", port);
1519 iport = ntohs(s->s_port);
1525 iport += arg->bundle->unit;
1526 res = server_TcpOpen(arg->bundle, iport);
1536 SetEscape(struct cmdargs const *arg)
1539 int argc = arg->argc - arg->argn;
1540 char const *const *argv = arg->argv + arg->argn;
1542 for (code = 0; code < 33; code++)
1543 arg->cx->physical->async.cfg.EscMap[code] = 0;
1545 while (argc-- > 0) {
1546 sscanf(*argv++, "%x", &code);
1548 arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7));
1549 arg->cx->physical->async.cfg.EscMap[32] = 1;
1555 SetInterfaceAddr(struct cmdargs const *arg)
1557 struct ncp *ncp = &arg->bundle->ncp;
1558 struct ncpaddr ncpaddr;
1559 const char *hisaddr;
1561 if (arg->argc > arg->argn + 4)
1565 memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range);
1566 memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range);
1567 ncp->ipcp.cfg.HaveTriggerAddress = 0;
1568 ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY;
1569 iplist_reset(&ncp->ipcp.cfg.peer_list);
1571 if (arg->argc > arg->argn) {
1572 if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn]))
1574 if (arg->argc > arg->argn+1) {
1575 hisaddr = arg->argv[arg->argn+1];
1576 if (arg->argc > arg->argn+2) {
1577 ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask =
1578 GetIpAddr(arg->argv[arg->argn+2]);
1579 if (arg->argc > arg->argn+3) {
1580 ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]);
1581 ncp->ipcp.cfg.HaveTriggerAddress = 1;
1587 /* 0.0.0.0 means any address (0 bits) */
1588 ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr);
1589 ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip);
1590 if (ncp->ipcp.my_ip.s_addr == INADDR_ANY)
1591 ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0);
1592 bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL);
1594 if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr,
1595 arg->bundle->phys_type.all & PHYS_AUTO))
1602 SetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq,
1603 u_int *maxtrm, int def)
1606 *timeout = DEF_FSMRETRY;
1611 long l = atol(argv[0]);
1613 if (l < MIN_FSMRETRY) {
1614 log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n",
1623 log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l);
1628 if (argc > 2 && maxtrm != NULL) {
1631 log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l);
1643 SetVariable(struct cmdargs const *arg)
1645 long long_val, param = (long)arg->cmd->args;
1646 int mode, dummyint, f, first, res;
1649 struct datalink *cx = arg->cx; /* LOCAL_CX uses this */
1650 struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */
1651 struct in_addr *ipaddr;
1652 struct ncpaddr ncpaddr[2];
1654 if (arg->argc > arg->argn)
1655 argp = arg->argv[arg->argn];
1661 if ((arg->cmd->lauth & LOCAL_CX) && !cx) {
1662 log_Printf(LogWARN, "set %s: No context (use the `link' command)\n",
1665 } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) {
1666 log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n",
1667 arg->cmd->name, cx->name);
1673 strncpy(arg->bundle->cfg.auth.key, argp,
1674 sizeof arg->bundle->cfg.auth.key - 1);
1675 arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0';
1679 switch (bundle_Phase(arg->bundle)) {
1681 log_Printf(LogWARN, "Altering authname while at phase %s\n",
1682 bundle_PhaseName(arg->bundle));
1685 case PHASE_ESTABLISH:
1686 strncpy(arg->bundle->cfg.auth.name, argp,
1687 sizeof arg->bundle->cfg.auth.name - 1);
1688 arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0';
1694 if (arg->argc == arg->argn + 3) {
1698 v1 = strtol(arg->argv[arg->argn], &end, 0);
1699 if (v1 < 0 || *end) {
1700 log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n",
1701 arg->argv[arg->argn]);
1706 v2 = strtol(arg->argv[arg->argn + 1], &end, 0);
1707 if (v2 < 0 || *end) {
1708 log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n",
1709 arg->argv[arg->argn + 1]);
1719 v3 = strtol(arg->argv[arg->argn + 2], &end, 0);
1720 if (v3 <= 0 || *end) {
1721 log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n",
1722 arg->argv[arg->argn + 2]);
1727 arg->bundle->ncp.mp.cfg.autoload.min = v1;
1728 arg->bundle->ncp.mp.cfg.autoload.max = v2;
1729 arg->bundle->ncp.mp.cfg.autoload.period = v3;
1730 mp_RestartAutoloadTimer(&arg->bundle->ncp.mp);
1732 log_Printf(LogWARN, "Set autoload requires three arguments\n");
1738 strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1);
1739 cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0';
1743 strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1);
1744 cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0';
1748 if (arg->argc > arg->argn) {
1749 l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]);
1750 if (l->ccp.cfg.deflate.out.winsize < 8 ||
1751 l->ccp.cfg.deflate.out.winsize > 15) {
1752 log_Printf(LogWARN, "%d: Invalid outgoing window size\n",
1753 l->ccp.cfg.deflate.out.winsize);
1754 l->ccp.cfg.deflate.out.winsize = 15;
1756 if (arg->argc > arg->argn+1) {
1757 l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]);
1758 if (l->ccp.cfg.deflate.in.winsize < 8 ||
1759 l->ccp.cfg.deflate.in.winsize > 15) {
1760 log_Printf(LogWARN, "%d: Invalid incoming window size\n",
1761 l->ccp.cfg.deflate.in.winsize);
1762 l->ccp.cfg.deflate.in.winsize = 15;
1765 l->ccp.cfg.deflate.in.winsize = 0;
1767 log_Printf(LogWARN, "No window size specified\n");
1774 if (arg->argc > arg->argn + 2) {
1779 if (arg->argc == arg->argn) {
1780 l->ccp.cfg.mppe.keybits = 0;
1781 l->ccp.cfg.mppe.state = MPPE_ANYSTATE;
1782 l->ccp.cfg.mppe.required = 0;
1786 if (!strcmp(argp, "*"))
1789 long_val = atol(argp);
1790 if (long_val != 40 && long_val != 56 && long_val != 128) {
1791 log_Printf(LogWARN, "%s: Invalid bits value\n", argp);
1797 if (arg->argc == arg->argn + 2) {
1798 if (!strcmp(arg->argv[arg->argn + 1], "*"))
1799 l->ccp.cfg.mppe.state = MPPE_ANYSTATE;
1800 else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless"))
1801 l->ccp.cfg.mppe.state = MPPE_STATELESS;
1802 else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful"))
1803 l->ccp.cfg.mppe.state = MPPE_STATEFUL;
1805 log_Printf(LogWARN, "%s: Invalid state value\n",
1806 arg->argv[arg->argn + 1]);
1811 l->ccp.cfg.mppe.state = MPPE_ANYSTATE;
1812 l->ccp.cfg.mppe.keybits = long_val;
1813 l->ccp.cfg.mppe.required = 1;
1818 physical_SetDeviceList(cx->physical, arg->argc - arg->argn,
1819 arg->argv + arg->argn);
1823 if (arg->argc > arg->argn) {
1825 sscanf(argp, "%lx", &ulong_val);
1826 cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val;
1828 log_Printf(LogWARN, "No accmap specified\n");
1834 mode = Nam2mode(argp);
1835 if (mode == PHYS_NONE || mode == PHYS_ALL) {
1836 log_Printf(LogWARN, "%s: Invalid mode\n", argp);
1840 bundle_SetMode(arg->bundle, cx, mode);
1844 switch (bundle_Phase(arg->bundle)) {
1847 case PHASE_ESTABLISH:
1848 /* Make sure none of our links are DATALINK_LCP or greater */
1849 if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) {
1850 log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n");
1856 log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n");
1862 long_val = atol(argp);
1863 if (long_val && long_val < MIN_MRU) {
1864 log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU);
1867 } else if (long_val > MAX_MRU) {
1868 log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU);
1872 arg->bundle->ncp.mp.cfg.mrru = long_val;
1876 long_val = 0; /* silence gcc */
1877 change = NULL; /* silence gcc */
1878 switch(arg->argc - arg->argn) {
1880 if (argp[strspn(argp, "0123456789")] != '\0') {
1886 long_val = atol(argp);
1887 change = &l->lcp.cfg.mru;
1888 if (long_val > l->lcp.cfg.max_mru) {
1889 log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val,
1890 l->lcp.cfg.max_mru);
1896 if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) {
1900 long_val = atol(arg->argv[arg->argn + 1]);
1901 change = &l->lcp.cfg.max_mru;
1902 if (long_val > MAX_MRU) {
1903 log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val,
1918 else if (long_val < MIN_MRU) {
1919 log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU);
1922 } else if (long_val > MAX_MRU) {
1923 log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU);
1928 if (l->lcp.cfg.mru > *change)
1929 l->lcp.cfg.mru = *change;
1933 long_val = 0; /* silence gcc */
1934 change = NULL; /* silence gcc */
1935 switch(arg->argc - arg->argn) {
1937 if (argp[strspn(argp, "0123456789")] != '\0') {
1943 long_val = atol(argp);
1944 change = &l->lcp.cfg.mtu;
1945 if (long_val > l->lcp.cfg.max_mtu) {
1946 log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val,
1947 l->lcp.cfg.max_mtu);
1953 if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) {
1957 long_val = atol(arg->argv[arg->argn + 1]);
1958 change = &l->lcp.cfg.max_mtu;
1959 if (long_val > MAX_MTU) {
1960 log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val,
1974 if (long_val && long_val < MIN_MTU) {
1975 log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU);
1978 } else if (long_val > MAX_MTU) {
1979 log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU);
1984 if (l->lcp.cfg.mtu > *change)
1985 l->lcp.cfg.mtu = *change;
1989 if (strcasecmp(argp, "active") == 0)
1990 cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ?
1991 atoi(arg->argv[arg->argn+1]) : 1;
1992 else if (strcasecmp(argp, "passive") == 0)
1993 cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE;
1995 log_Printf(LogWARN, "%s: Invalid openmode\n", argp);
2001 strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1);
2002 cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0';
2003 cx->phone.alt = cx->phone.next = NULL;
2007 strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1);
2008 cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0';
2012 long_val = atol(argp);
2013 arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val;
2017 strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1);
2018 cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0';
2021 case VAR_IDLETIMEOUT:
2022 if (arg->argc > arg->argn+2) {
2023 log_Printf(LogWARN, "Too many idle timeout values\n");
2025 } else if (arg->argc == arg->argn) {
2026 log_Printf(LogWARN, "Too few idle timeout values\n");
2029 unsigned long timeout, min;
2031 timeout = strtoul(argp, NULL, 10);
2032 min = arg->bundle->cfg.idle.min_timeout;
2033 if (arg->argc == arg->argn + 2)
2034 min = strtoul(arg->argv[arg->argn + 1], NULL, 10);
2035 bundle_SetIdleTimer(arg->bundle, timeout, min);
2041 if (arg->argc > arg->argn + 2) {
2042 log_Printf(LogWARN, "Too many RADIUS alive interval values\n");
2044 } else if (arg->argc == arg->argn) {
2045 log_Printf(LogWARN, "Too few RADIUS alive interval values\n");
2048 arg->bundle->radius.alive.interval = atoi(argp);
2049 if (arg->bundle->radius.alive.interval && !arg->bundle->radius.cfg.file) {
2050 log_Printf(LogWARN, "rad_alive requires radius to be configured\n");
2052 } else if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) {
2053 if (arg->bundle->radius.alive.interval)
2054 radius_StartTimer(arg->bundle);
2056 radius_StopTimer(&arg->bundle->radius);
2063 long_val = atol(argp);
2064 if (long_val < MIN_LQRPERIOD) {
2065 log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n",
2066 long_val, MIN_LQRPERIOD);
2069 l->lcp.cfg.lqrperiod = long_val;
2073 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
2074 &cx->physical->link.lcp.cfg.fsm.timeout,
2075 &cx->physical->link.lcp.cfg.fsm.maxreq,
2076 &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES);
2080 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
2081 &cx->chap.auth.cfg.fsm.timeout,
2082 &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES);
2086 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
2087 &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq,
2088 NULL, DEF_FSMAUTHTRIES);
2092 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
2093 &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq,
2094 &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES);
2098 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
2099 &arg->bundle->ncp.ipcp.cfg.fsm.timeout,
2100 &arg->bundle->ncp.ipcp.cfg.fsm.maxreq,
2101 &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES);
2105 case VAR_IPV6CPRETRY:
2106 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
2107 &arg->bundle->ncp.ipv6cp.cfg.fsm.timeout,
2108 &arg->bundle->ncp.ipv6cp.cfg.fsm.maxreq,
2109 &arg->bundle->ncp.ipv6cp.cfg.fsm.maxtrm, DEF_FSMTRIES);
2115 if (param == VAR_DNS) {
2116 ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns;
2117 ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE;
2119 ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns;
2120 ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY;
2123 if (arg->argc > arg->argn) {
2124 ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]);
2125 if (!ncpaddr_getip4(ncpaddr, ipaddr))
2127 if (arg->argc > arg->argn+1) {
2128 ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]);
2129 if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1))
2133 if (ipaddr[0].s_addr == INADDR_ANY) {
2134 ipaddr[0] = ipaddr[1];
2135 ipaddr[1].s_addr = INADDR_ANY;
2137 if (ipaddr[0].s_addr == INADDR_NONE) {
2138 ipaddr[0] = ipaddr[1];
2139 ipaddr[1].s_addr = INADDR_NONE;
2145 cx->cfg.callback.opmask = 0;
2146 for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) {
2147 if (!strcasecmp(arg->argv[dummyint], "auth"))
2148 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH);
2149 else if (!strcasecmp(arg->argv[dummyint], "cbcp"))
2150 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP);
2151 else if (!strcasecmp(arg->argv[dummyint], "e.164")) {
2152 if (dummyint == arg->argc - 1)
2153 log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n");
2155 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164);
2156 strncpy(cx->cfg.callback.msg, arg->argv[++dummyint],
2157 sizeof cx->cfg.callback.msg - 1);
2158 cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0';
2160 } else if (!strcasecmp(arg->argv[dummyint], "none"))
2161 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE);
2167 if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE))
2168 cx->cfg.callback.opmask = 0;
2172 cx->cfg.cbcp.delay = 0;
2173 *cx->cfg.cbcp.phone = '\0';
2174 cx->cfg.cbcp.fsmretry = DEF_FSMRETRY;
2175 if (arg->argc > arg->argn) {
2176 strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn],
2177 sizeof cx->cfg.cbcp.phone - 1);
2178 cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0';
2179 if (arg->argc > arg->argn + 1) {
2180 cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]);
2181 if (arg->argc > arg->argn + 2) {
2182 long_val = atol(arg->argv[arg->argn + 2]);
2183 if (long_val < MIN_FSMRETRY)
2184 log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n",
2185 long_val, MIN_FSMRETRY);
2187 cx->cfg.cbcp.fsmretry = long_val;
2194 arg->bundle->cfg.choked.timeout = atoi(argp);
2195 if (arg->bundle->cfg.choked.timeout <= 0)
2196 arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT;
2200 long_val = atol(argp);
2201 arg->bundle->ncp.cfg.sendpipe = long_val;
2205 long_val = atol(argp);
2206 arg->bundle->ncp.cfg.recvpipe = long_val;
2212 *arg->bundle->radius.cfg.file = '\0';
2213 else if (access(argp, R_OK)) {
2214 log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno));
2218 strncpy(arg->bundle->radius.cfg.file, argp,
2219 sizeof arg->bundle->radius.cfg.file - 1);
2220 arg->bundle->radius.cfg.file
2221 [sizeof arg->bundle->radius.cfg.file - 1] = '\0';
2228 if (strcasecmp(argp, "off")) {
2229 long_val = atol(argp);
2232 cx->physical->cfg.cd.delay = long_val;
2233 cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ?
2234 CD_REQUIRED : CD_VARIABLE;
2236 cx->physical->cfg.cd.necessity = CD_NOTREQUIRED;
2238 cx->physical->cfg.cd.delay = 0;
2239 cx->physical->cfg.cd.necessity = CD_DEFAULT;
2244 if (arg->argc == arg->argn + 1)
2245 res = physical_SetParity(arg->cx->physical, argp);
2247 log_Printf(LogWARN, "Parity value must be odd, even or none\n");
2253 if (strcasecmp(argp, "on") == 0)
2254 physical_SetRtsCts(arg->cx->physical, 1);
2255 else if (strcasecmp(argp, "off") == 0)
2256 physical_SetRtsCts(arg->cx->physical, 0);
2258 log_Printf(LogWARN, "RTS/CTS value must be on or off\n");
2263 case VAR_URGENTPORTS:
2264 if (arg->argn == arg->argc) {
2265 ncp_SetUrgentTOS(&arg->bundle->ncp);
2266 ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
2267 ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
2268 } else if (!strcasecmp(arg->argv[arg->argn], "udp")) {
2269 ncp_SetUrgentTOS(&arg->bundle->ncp);
2270 if (arg->argn == arg->argc - 1)
2271 ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
2272 else for (f = arg->argn + 1; f < arg->argc; f++)
2273 if (*arg->argv[f] == '+')
2274 ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
2275 else if (*arg->argv[f] == '-')
2276 ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
2279 ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
2280 ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f]));
2282 } else if (arg->argn == arg->argc - 1 &&
2283 !strcasecmp(arg->argv[arg->argn], "none")) {
2284 ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
2285 ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
2286 ncp_ClearUrgentTOS(&arg->bundle->ncp);
2288 ncp_SetUrgentTOS(&arg->bundle->ncp);
2290 if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc)
2291 ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
2293 for (f = first; f < arg->argc; f++)
2294 if (*arg->argv[f] == '+')
2295 ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
2296 else if (*arg->argv[f] == '-')
2297 ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
2300 ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
2301 ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f]));
2307 if (strcasecmp(argp, "3Com") == 0)
2308 physical_SetPPPoEnonstandard(arg->cx->physical, 1);
2309 else if (strcasecmp(argp, "standard") == 0)
2310 physical_SetPPPoEnonstandard(arg->cx->physical, 0);
2312 log_Printf(LogWARN, "PPPoE standard value must be \"standard\" or \"3Com\"\n");
2319 if (strcasecmp(argp, "default") == 0)
2320 arg->bundle->radius.port_id_type = RPI_DEFAULT;
2321 else if (strcasecmp(argp, "pid") == 0)
2322 arg->bundle->radius.port_id_type = RPI_PID;
2323 else if (strcasecmp(argp, "ifnum") == 0)
2324 arg->bundle->radius.port_id_type = RPI_IFNUM;
2325 else if (strcasecmp(argp, "tunnum") == 0)
2326 arg->bundle->radius.port_id_type = RPI_TUNNUM;
2329 "RADIUS port id must be one of \"default\", \"pid\", \"ifnum\" or \"tunnum\"\n");
2333 if (arg->bundle->radius.port_id_type && !arg->bundle->radius.cfg.file) {
2334 log_Printf(LogWARN, "rad_port_id requires radius to be configured\n");
2345 static struct cmdtab const SetCommands[] = {
2346 {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2347 "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP},
2348 {"authkey", "key", SetVariable, LOCAL_AUTH,
2349 "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY},
2350 {"authname", NULL, SetVariable, LOCAL_AUTH,
2351 "authentication name", "set authname name", (const void *)VAR_AUTHNAME},
2352 {"autoload", NULL, SetVariable, LOCAL_AUTH,
2353 "auto link [de]activation", "set autoload maxtime maxload mintime minload",
2354 (const void *)VAR_AUTOLOAD},
2355 {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX,
2356 "datalink bandwidth", "set bandwidth value", NULL},
2357 {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2358 "callback control", "set callback [none|auth|cbcp|"
2359 "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK},
2360 {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2361 "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]",
2362 (const void *)VAR_CBCP},
2363 {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
2364 "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY},
2365 {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement",
2366 "set cd value[!]", (const void *)VAR_CD},
2367 {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX,
2368 "CHAP retries", "set chapretry value [attempts]",
2369 (const void *)VAR_CHAPRETRY},
2370 {"choked", NULL, SetVariable, LOCAL_AUTH,
2371 "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED},
2372 {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX,
2373 "Use hardware flow control", "set ctsrts [on|off]",
2374 (const char *)VAR_CRTSCTS},
2375 {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
2376 "deflate window sizes", "set deflate out-winsize in-winsize",
2377 (const void *) VAR_WINSIZE},
2379 {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
2380 "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]",
2381 (const void *) VAR_MPPE},
2383 {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX,
2384 "physical device name", "set device|line device-name[,device-name]",
2385 (const void *) VAR_DEVICE},
2386 {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2387 "dialing script", "set dial chat-script", (const void *) VAR_DIAL},
2388 {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server",
2389 "set dns pri-addr [sec-addr]", (const void *)VAR_DNS},
2390 {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH,
2391 "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]", NULL},
2392 {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX,
2393 "escape characters", "set escape hex-digit ...", NULL},
2394 {"filter", NULL, filter_Set, LOCAL_AUTH,
2395 "packet filters", "set filter alive|dial|in|out rule-no permit|deny "
2396 "[src_addr[/width]] [dst_addr[/width]] [proto "
2397 "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]", NULL},
2398 {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2399 "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP},
2400 {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address",
2401 "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]", NULL},
2402 {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue",
2403 "set ifqueue packets", (const void *)VAR_IFQUEUE},
2404 {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries",
2405 "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY},
2406 {"ipv6cpretry", "ipv6cpretries", SetVariable, LOCAL_AUTH, "IPV6CP retries",
2407 "set ipv6cpretry value [attempts]", (const void *)VAR_IPV6CPRETRY},
2408 {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries",
2409 "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY},
2410 {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level",
2411 "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|"
2412 "id0|ipcp|lcp|lqm|phase|physical|radius|sync|tcp/ip|timer|tun...", NULL},
2413 {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2414 "login script", "set login chat-script", (const void *) VAR_LOGIN},
2415 {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2416 "logout script", "set logout chat-script", (const void *) VAR_LOGOUT},
2417 {"lqrperiod", "echoperiod", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
2418 "LQR period", "set lqr/echo period value", (const void *)VAR_LQRPERIOD},
2419 {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value",
2420 "set mode interactive|auto|ddial|background", (const void *)VAR_MODE},
2421 {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value",
2422 "set mrru value", (const void *)VAR_MRRU},
2423 {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2424 "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU},
2425 {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2426 "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU},
2427 {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server",
2428 "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS},
2429 {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode",
2430 "set openmode active|passive [secs]", (const void *)VAR_OPENMODE},
2431 {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries",
2432 "set papretry value [attempts]", (const void *)VAR_PAPRETRY},
2433 {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity",
2434 "set parity [odd|even|none]", (const void *)VAR_PARITY},
2435 {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)",
2436 "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE},
2437 {"proctitle", "title", SetProcTitle, LOCAL_AUTH,
2438 "Process title", "set proctitle [value]", NULL},
2440 {"radius", NULL, SetVariable, LOCAL_AUTH,
2441 "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS},
2442 {"rad_alive", NULL, SetVariable, LOCAL_AUTH,
2443 "Raduis alive interval", "set rad_alive value",
2444 (const void *)VAR_RAD_ALIVE},
2445 {"rad_port_id", NULL, SetVariable, LOCAL_AUTH,
2446 "NAS-Port-Id", "set rad_port_id [default|pid|ifnum|tunnum]", (const void *)VAR_PORT_ID},
2448 {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX,
2449 "Reconnect timeout", "set reconnect value ntries", NULL},
2450 {"recvpipe", NULL, SetVariable, LOCAL_AUTH,
2451 "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE},
2452 {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX,
2453 "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]", NULL},
2454 {"sendpipe", NULL, SetVariable, LOCAL_AUTH,
2455 "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE},
2456 {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port",
2457 "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]",
2459 {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX,
2460 "physical speed", "set speed value|sync", NULL},
2461 {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX,
2462 "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]", NULL},
2463 {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout",
2464 "set timeout idletime", (const void *)VAR_IDLETIMEOUT},
2465 {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports",
2466 "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS},
2467 {"vj", NULL, ipcp_vjset, LOCAL_AUTH,
2468 "vj values", "set vj slots|slotcomp [value]", NULL},
2469 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
2470 "Display this message", "set help|? [command]", SetCommands},
2471 {"pppoe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
2472 "Connect using standard/3Com mode", "set pppoe [standard|3Com]",
2473 (const char *)VAR_PPPOE},
2474 {NULL, NULL, NULL, 0, NULL, NULL, NULL},
2478 SetCommand(struct cmdargs const *arg)
2480 if (arg->argc > arg->argn)
2481 FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv,
2482 arg->prompt, arg->cx);
2483 else if (arg->prompt)
2484 prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for"
2487 log_Printf(LogWARN, "set command must have arguments\n");
2493 AddCommand(struct cmdargs const *arg)
2496 struct ncprange dest;
2497 struct in_addr host;
2499 struct in6_addr host6;
2501 int dest_default, gw_arg, addrs;
2503 if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2)
2508 if (arg->argc == arg->argn + 2) {
2509 if (!strcasecmp(arg->argv[arg->argn], "default"))
2512 if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]))
2514 if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6))
2515 addrs = ROUTE_DSTMYADDR;
2516 else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7))
2517 addrs = ROUTE_DSTMYADDR6;
2518 else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7))
2519 addrs = ROUTE_DSTHISADDR;
2520 else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8))
2521 addrs = ROUTE_DSTHISADDR6;
2522 else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4))
2523 addrs = ROUTE_DSTDNS0;
2524 else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4))
2525 addrs = ROUTE_DSTDNS1;
2529 if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) {
2530 addrs = ROUTE_DSTMYADDR;
2531 host = arg->bundle->ncp.ipcp.my_ip;
2532 } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) {
2533 addrs = ROUTE_DSTHISADDR;
2534 host = arg->bundle->ncp.ipcp.peer_ip;
2535 } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) {
2536 addrs = ROUTE_DSTDNS0;
2537 host = arg->bundle->ncp.ipcp.ns.dns[0];
2538 } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) {
2539 addrs = ROUTE_DSTDNS1;
2540 host = arg->bundle->ncp.ipcp.ns.dns[1];
2542 host = GetIpAddr(arg->argv[arg->argn]);
2543 if (host.s_addr == INADDR_NONE) {
2544 log_Printf(LogWARN, "%s: Invalid destination address\n",
2545 arg->argv[arg->argn]);
2549 ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1]));
2553 if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) {
2554 ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip);
2555 addrs |= ROUTE_GWHISADDR;
2557 } else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) {
2558 if (!ncpaddr_getip6(&arg->bundle->ncp.ipv6cp.hisaddr, &host6))
2559 memset(&host6, '\0', sizeof host6);
2560 ncpaddr_setip6(&gw, &host6);
2561 addrs |= ROUTE_GWHISADDR6;
2564 if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) {
2565 log_Printf(LogWARN, "%s: Invalid gateway address\n",
2566 arg->argv[arg->argn + gw_arg]);
2572 ncprange_setdefault(&dest, ncpaddr_family(&gw));
2574 if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0,
2575 ((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0)
2576 && addrs != ROUTE_STATIC)
2577 route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw);
2583 DeleteCommand(struct cmdargs const *arg)
2585 struct ncprange dest;
2588 if (arg->argc == arg->argn+1) {
2589 if(strcasecmp(arg->argv[arg->argn], "all") == 0) {
2590 route_IfDelete(arg->bundle, 0);
2591 route_DeleteAll(&arg->bundle->ncp.route);
2594 if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) {
2595 ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip);
2596 addrs = ROUTE_DSTMYADDR;
2598 } else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) {
2599 ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr);
2600 addrs = ROUTE_DSTMYADDR6;
2602 } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) {
2603 ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip);
2604 addrs = ROUTE_DSTHISADDR;
2606 } else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) {
2607 ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr);
2608 addrs = ROUTE_DSTHISADDR6;
2610 } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) {
2611 ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]);
2612 addrs = ROUTE_DSTDNS0;
2613 } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) {
2614 ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]);
2615 addrs = ROUTE_DSTDNS1;
2617 ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]);
2618 addrs = ROUTE_STATIC;
2620 rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0);
2621 route_Delete(&arg->bundle->ncp.route, addrs, &dest);
2631 NatEnable(struct cmdargs const *arg)
2633 if (arg->argc == arg->argn+1) {
2634 if (strcasecmp(arg->argv[arg->argn], "yes") == 0) {
2635 if (!arg->bundle->NatEnabled) {
2636 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED)
2637 LibAliasSetAddress(la, arg->bundle->ncp.ipcp.my_ip);
2638 arg->bundle->NatEnabled = 1;
2641 } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) {
2642 arg->bundle->NatEnabled = 0;
2643 opt_disable(arg->bundle, OPT_IFACEALIAS);
2644 /* Don't iface_Clear() - there may be manually configured addresses */
2654 NatOption(struct cmdargs const *arg)
2656 long param = (long)arg->cmd->args;
2658 if (arg->argc == arg->argn+1) {
2659 if (strcasecmp(arg->argv[arg->argn], "yes") == 0) {
2660 if (arg->bundle->NatEnabled) {
2661 LibAliasSetMode(la, param, param);
2664 log_Printf(LogWARN, "nat not enabled\n");
2665 } else if (strcmp(arg->argv[arg->argn], "no") == 0) {
2666 if (arg->bundle->NatEnabled) {
2667 LibAliasSetMode(la, 0, param);
2670 log_Printf(LogWARN, "nat not enabled\n");
2675 #endif /* #ifndef NONAT */
2678 LinkCommand(struct cmdargs const *arg)
2680 if (arg->argc > arg->argn+1) {
2681 char namelist[LINE_LEN];
2682 struct datalink *cx;
2686 if (!strcmp(arg->argv[arg->argn], "*")) {
2687 struct datalink *dl;
2689 cx = arg->bundle->links;
2691 /* Watch it, the command could be a ``remove'' */
2693 FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv,
2695 for (cx = arg->bundle->links; cx; cx = cx->next)
2697 break; /* Pointer's still valid ! */
2700 strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1);
2701 namelist[sizeof namelist - 1] = '\0';
2702 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", "))
2703 if (!bundle2datalink(arg->bundle, name)) {
2704 log_Printf(LogWARN, "link: %s: Invalid link name\n", name);
2708 strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1);
2709 namelist[sizeof namelist - 1] = '\0';
2710 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) {
2711 cx = bundle2datalink(arg->bundle, name);
2713 FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv,
2716 log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name);
2724 log_Printf(LogWARN, "usage: %s\n", arg->cmd->syntax);
2729 command_ChooseLink(struct cmdargs const *arg)
2732 return &arg->cx->physical->link;
2733 else if (!arg->bundle->ncp.mp.cfg.mrru) {
2734 struct datalink *dl = bundle2datalink(arg->bundle, NULL);
2736 return &dl->physical->link;
2738 return &arg->bundle->ncp.mp.link;
2742 ident_cmd(const char *cmd, unsigned *keep, unsigned *add)
2751 *add = NEG_ACCEPTED;
2765 *keep = NEG_HISMASK;
2775 *keep = NEG_HISMASK;
2786 OptSet(struct cmdargs const *arg)
2788 int opt = (int)(long)arg->cmd->args;
2789 unsigned keep; /* Keep this opt */
2790 unsigned add; /* Add this opt */
2792 if (ident_cmd(arg->argv[arg->argn - 2], &keep, &add) == NULL)
2796 if (add == NEG_ENABLED && opt == OPT_IPV6CP && !probe.ipv6_available) {
2797 log_Printf(LogWARN, "IPv6 is not available on this machine\n");
2801 if (!add && ((opt == OPT_NAS_IP_ADDRESS &&
2802 !Enabled(arg->bundle, OPT_NAS_IDENTIFIER)) ||
2803 (opt == OPT_NAS_IDENTIFIER &&
2804 !Enabled(arg->bundle, OPT_NAS_IP_ADDRESS)))) {
2806 "Cannot disable both NAS-IP-Address and NAS-Identifier\n");
2811 opt_enable(arg->bundle, opt);
2813 opt_disable(arg->bundle, opt);
2819 IfaceAliasOptSet(struct cmdargs const *arg)
2821 unsigned long long save = arg->bundle->cfg.optmask;
2822 int result = OptSet(arg);
2825 if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) {
2826 arg->bundle->cfg.optmask = save;
2827 log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n");
2835 NegotiateSet(struct cmdargs const *arg)
2837 long param = (long)arg->cmd->args;
2838 struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */
2839 struct datalink *cx = arg->cx; /* LOCAL_CX uses this */
2841 unsigned keep; /* Keep these bits */
2842 unsigned add; /* Add these bits */
2844 if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL)
2847 if ((arg->cmd->lauth & LOCAL_CX) && !cx) {
2848 log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n",
2849 cmd, arg->cmd->name);
2851 } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) {
2852 log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n",
2853 cmd, arg->cmd->name, cx->name);
2859 cx->physical->link.lcp.cfg.acfcomp &= keep;
2860 cx->physical->link.lcp.cfg.acfcomp |= add;
2863 cx->physical->link.lcp.cfg.chap05 &= keep;
2864 cx->physical->link.lcp.cfg.chap05 |= add;
2868 cx->physical->link.lcp.cfg.chap80nt &= keep;
2869 cx->physical->link.lcp.cfg.chap80nt |= add;
2872 cx->physical->link.lcp.cfg.chap80lm &= keep;
2873 cx->physical->link.lcp.cfg.chap80lm |= add;
2876 cx->physical->link.lcp.cfg.chap81 &= keep;
2877 cx->physical->link.lcp.cfg.chap81 |= add;
2880 l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep;
2881 l->ccp.cfg.neg[CCP_NEG_MPPE] |= add;
2885 l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep;
2886 l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add;
2889 arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep;
2890 arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add;
2892 case NEG_ECHO: /* probably misplaced in this function ! */
2893 if (cx->physical->link.lcp.cfg.echo && !add) {
2894 cx->physical->link.lcp.cfg.echo = 0;
2895 cx->physical->hdlc.lqm.method &= ~LQM_ECHO;
2896 if (cx->physical->hdlc.lqm.method & LQM_ECHO &&
2897 !cx->physical->link.lcp.want_lqrperiod &&
2898 cx->physical->hdlc.lqm.timer.load) {
2899 cx->physical->hdlc.lqm.timer.load = 0;
2900 lqr_StopTimer(cx->physical);
2902 } else if (!cx->physical->link.lcp.cfg.echo && add) {
2903 cx->physical->link.lcp.cfg.echo = 1;
2904 cx->physical->hdlc.lqm.method |= LQM_ECHO;
2905 cx->physical->hdlc.lqm.timer.load =
2906 cx->physical->link.lcp.cfg.lqrperiod * SECTICKS;
2907 if (cx->physical->link.lcp.fsm.state == ST_OPENED)
2908 (*cx->physical->hdlc.lqm.timer.func)(&cx->physical->link.lcp);
2912 arg->bundle->ncp.mp.cfg.negenddisc &= keep;
2913 arg->bundle->ncp.mp.cfg.negenddisc |= add;
2916 cx->physical->link.lcp.cfg.lqr &= keep;
2917 cx->physical->link.lcp.cfg.lqr |= add;
2920 cx->physical->link.lcp.cfg.pap &= keep;
2921 cx->physical->link.lcp.cfg.pap |= add;
2923 case NEG_PPPDDEFLATE:
2924 l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep;
2925 l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add;
2928 l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep;
2929 l->ccp.cfg.neg[CCP_NEG_PRED1] |= add;
2932 cx->physical->link.lcp.cfg.protocomp &= keep;
2933 cx->physical->link.lcp.cfg.protocomp |= add;
2936 switch (bundle_Phase(arg->bundle)) {
2939 case PHASE_ESTABLISH:
2940 /* Make sure none of our links are DATALINK_LCP or greater */
2941 if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) {
2942 log_Printf(LogWARN, "shortseq: Only changable before"
2943 " LCP negotiations\n");
2948 log_Printf(LogWARN, "shortseq: Only changable at phase"
2949 " DEAD/ESTABLISH\n");
2952 arg->bundle->ncp.mp.cfg.shortseq &= keep;
2953 arg->bundle->ncp.mp.cfg.shortseq |= add;
2956 arg->bundle->ncp.ipcp.cfg.vj.neg &= keep;
2957 arg->bundle->ncp.ipcp.cfg.vj.neg |= add;
2964 static struct cmdtab const NegotiateCommands[] = {
2965 {"echo", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, "Send echo requests",
2966 "disable|enable", (const void *)NEG_ECHO},
2967 {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH,
2968 "filter on PPPoUDP payloads", "disable|enable",
2969 (const void *)OPT_FILTERDECAP},
2970 {"force-scripts", NULL, OptSet, LOCAL_AUTH,
2971 "Force execution of the configured chat scripts", "disable|enable",
2972 (const void *)OPT_FORCE_SCRIPTS},
2973 {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids",
2974 "disable|enable", (const void *)OPT_IDCHECK},
2975 {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH,
2976 "retain interface addresses", "disable|enable",
2977 (const void *)OPT_IFACEALIAS},
2979 {"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol",
2980 "disable|enable", (const void *)OPT_IPCP},
2981 {"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol",
2982 "disable|enable", (const void *)OPT_IPV6CP},
2984 {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader",
2985 "disable|enable", (const void *)OPT_KEEPSESSION},
2986 {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface",
2987 "disable|enable", (const void *)OPT_LOOPBACK},
2988 {"nas-ip-address", NULL, OptSet, LOCAL_AUTH, "Send NAS-IP-Address to RADIUS",
2989 "disable|enable", (const void *)OPT_NAS_IP_ADDRESS},
2990 {"nas-identifier", NULL, OptSet, LOCAL_AUTH, "Send NAS-Identifier to RADIUS",
2991 "disable|enable", (const void *)OPT_NAS_IDENTIFIER},
2992 {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file",
2993 "disable|enable", (const void *)OPT_PASSWDAUTH},
2994 {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry",
2995 "disable|enable", (const void *)OPT_PROXY},
2996 {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts",
2997 "disable|enable", (const void *)OPT_PROXYALL},
2998 {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes",
2999 "disable|enable", (const void *)OPT_SROUTES},
3000 {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options",
3001 "disable|enable", (const void *)OPT_TCPMSSFIXUP},
3002 {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput",
3003 "disable|enable", (const void *)OPT_THROUGHPUT},
3004 {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp",
3005 "disable|enable", (const void *)OPT_UTMP},
3008 #define NEG_OPT_MAX 17 /* accept/deny allowed below and not above */
3010 #define NEG_OPT_MAX 15
3013 {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3014 "Address & Control field compression", "accept|deny|disable|enable",
3015 (const void *)NEG_ACFCOMP},
3016 {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3017 "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable",
3018 (const void *)NEG_CHAP05},
3020 {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3021 "Microsoft (NT) CHAP", "accept|deny|disable|enable",
3022 (const void *)NEG_CHAP80},
3023 {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3024 "Microsoft (NT) CHAP", "accept|deny|disable|enable",
3025 (const void *)NEG_CHAP80LM},
3026 {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3027 "Microsoft CHAP v2", "accept|deny|disable|enable",
3028 (const void *)NEG_CHAP81},
3029 {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
3030 "MPPE encryption", "accept|deny|disable|enable",
3031 (const void *)NEG_MPPE},
3033 {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
3034 "Deflate compression", "accept|deny|disable|enable",
3035 (const void *)NEG_DEFLATE},
3036 {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
3037 "Deflate (type 24) compression", "accept|deny|disable|enable",
3038 (const void *)NEG_PPPDDEFLATE},
3039 {"dns", NULL, NegotiateSet, LOCAL_AUTH,
3040 "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS},
3041 {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation",
3042 "accept|deny|disable|enable", (const void *)NEG_ENDDISC},
3043 {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3044 "Link Quality Reports", "accept|deny|disable|enable",
3045 (const void *)NEG_LQR},
3046 {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3047 "Password Authentication protocol", "accept|deny|disable|enable",
3048 (const void *)NEG_PAP},
3049 {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
3050 "Predictor 1 compression", "accept|deny|disable|enable",
3051 (const void *)NEG_PRED1},
3052 {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
3053 "Protocol field compression", "accept|deny|disable|enable",
3054 (const void *)NEG_PROTOCOMP},
3055 {"shortseq", NULL, NegotiateSet, LOCAL_AUTH,
3056 "MP Short Sequence Numbers", "accept|deny|disable|enable",
3057 (const void *)NEG_SHORTSEQ},
3058 {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH,
3059 "Van Jacobson header compression", "accept|deny|disable|enable",
3060 (const void *)NEG_VJCOMP},
3061 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
3062 "Display this message", "accept|deny|disable|enable help|? [value]",
3064 {NULL, NULL, NULL, 0, NULL, NULL, NULL},
3068 NegotiateCommand(struct cmdargs const *arg)
3070 if (arg->argc > arg->argn) {
3071 char const *argv[3];
3075 if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL)
3079 for (n = arg->argn; n < arg->argc; n++) {
3080 argv[1] = arg->argv[n];
3081 FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ?
3082 0 : NEG_OPT_MAX), 2, 1, argv, arg->prompt, arg->cx);
3084 } else if (arg->prompt)
3085 prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n",
3086 arg->argv[arg->argn-1]);
3088 log_Printf(LogWARN, "%s command must have arguments\n",
3089 arg->argv[arg->argn] );
3095 command_ShowNegval(unsigned val)
3098 case 1: return "disabled & accepted";
3099 case 2: return "enabled & denied";
3100 case 3: return "enabled & accepted";
3102 return "disabled & denied";
3106 ClearCommand(struct cmdargs const *arg)
3108 struct pppThroughput *t;
3109 struct datalink *cx;
3112 if (arg->argc < arg->argn + 1)
3115 if (strcasecmp(arg->argv[arg->argn], "physical") == 0) {
3118 cx = bundle2datalink(arg->bundle, NULL);
3120 log_Printf(LogWARN, "A link must be specified for ``clear physical''\n");
3123 t = &cx->physical->link.stats.total;
3124 } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0)
3125 t = &arg->bundle->ncp.ipcp.throughput;
3127 else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0)
3128 t = &arg->bundle->ncp.ipv6cp.throughput;
3133 if (arg->argc > arg->argn + 1) {
3135 for (i = arg->argn + 1; i < arg->argc; i++)
3136 if (strcasecmp(arg->argv[i], "overall") == 0)
3137 clear_type |= THROUGHPUT_OVERALL;
3138 else if (strcasecmp(arg->argv[i], "current") == 0)
3139 clear_type |= THROUGHPUT_CURRENT;
3140 else if (strcasecmp(arg->argv[i], "peak") == 0)
3141 clear_type |= THROUGHPUT_PEAK;
3145 clear_type = THROUGHPUT_ALL;
3147 throughput_clear(t, clear_type, arg->prompt);
3152 RunListCommand(struct cmdargs const *arg)
3154 const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???";
3157 if (arg->cmd->args == NatCommands &&
3158 tolower(*arg->argv[arg->argn - 1]) == 'a') {
3160 prompt_Printf(arg->prompt, "The alias command is deprecated\n");
3162 log_Printf(LogWARN, "The alias command is deprecated\n");
3166 if (arg->argc > arg->argn)
3167 FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv,
3168 arg->prompt, arg->cx);
3169 else if (arg->prompt)
3170 prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help"
3171 " <option>' for syntax help.\n", cmd, cmd);
3173 log_Printf(LogWARN, "%s command must have arguments\n", cmd);
3179 IfaceAddCommand(struct cmdargs const *arg)
3181 struct ncpaddr peer, addr;
3182 struct ncprange ifa;
3183 struct in_addr mask;
3186 if (arg->argc == arg->argn + 1) {
3187 if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn]))
3189 ncpaddr_init(&peer);
3191 if (arg->argc == arg->argn + 2) {
3192 if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn]))
3195 } else if (arg->argc == arg->argn + 3) {
3196 if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn]))
3198 if (ncpaddr_family(&addr) != AF_INET)
3200 ncprange_sethost(&ifa, &addr);
3201 if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1]))
3203 if (!ncpaddr_getip4(&addr, &mask))
3205 if (!ncprange_setip4mask(&ifa, mask))
3211 if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n]))
3214 if (ncprange_family(&ifa) != ncpaddr_family(&peer)) {
3215 log_Printf(LogWARN, "IfaceAddCommand: src and dst address families"
3221 how = IFACE_ADD_LAST;
3223 how |= IFACE_FORCE_ADD;
3225 return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how);
3229 IfaceDeleteCommand(struct cmdargs const *arg)
3232 struct in_addr ifa4;
3235 if (arg->argc != arg->argn + 1)
3238 if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn]))
3241 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED &&
3242 ncpaddr_getip4(&ifa, &ifa4) &&
3243 arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) {
3244 log_Printf(LogWARN, "%s: Cannot remove active interface address\n",
3245 ncpaddr_ntoa(&ifa));
3249 ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa);
3253 else if (arg->prompt)
3254 prompt_Printf(arg->prompt, "%s: No such interface address\n",
3255 ncpaddr_ntoa(&ifa));
3257 log_Printf(LogWARN, "%s: No such interface address\n",
3258 ncpaddr_ntoa(&ifa));
3265 IfaceClearCommand(struct cmdargs const *arg)
3270 if (arg->argc == arg->argn + 1) {
3271 if (strcasecmp(arg->argv[arg->argn], "inet") == 0)
3274 else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0)
3279 } else if (arg->argc != arg->argn)
3282 how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED ||
3283 arg->bundle->phys_type.all & PHYS_AUTO ?
3284 IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL;
3285 iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how);
3291 SetProcTitle(struct cmdargs const *arg)
3293 static char title[LINE_LEN];
3294 char *argv[MAXARGS];
3295 int argc = arg->argc - arg->argn;
3297 if (arg->argc <= arg->argn) {
3302 if ((unsigned)argc >= sizeof argv / sizeof argv[0]) {
3303 argc = sizeof argv / sizeof argv[0] - 1;
3304 log_Printf(LogWARN, "Truncating proc title to %d args\n", argc);
3306 command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid());
3307 Concatinate(title, sizeof title, argc, (const char *const *)argv);
3309 command_Free(argc, argv);