637 {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 638 "proxy control", "nat proxy server host[:port] ..."}, 639 {"same_ports", NULL, NatOption, LOCAL_AUTH, 640 "try to leave port numbers unchanged", "nat same_ports yes|no", 641 (const void *) PKT_ALIAS_SAME_PORTS}, 642 {"target", NULL, nat_SetTarget, LOCAL_AUTH, 643 "Default address for incoming connections", "nat target addr" }, 644 {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 645 "translate unregistered (private) IP address space only", 646 "nat unregistered_only yes|no", 647 (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 648 {"use_sockets", NULL, NatOption, LOCAL_AUTH, 649 "allocate host sockets", "nat use_sockets yes|no", 650 (const void *) PKT_ALIAS_USE_SOCKETS}, 651 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 652 "Display this message", "nat help|? [command]", NatCommands}, 653 {NULL, NULL, NULL}, 654}; 655#endif 656 657static struct cmdtab const AllowCommands[] = { 658 {"modes", "mode", AllowModes, LOCAL_AUTH, 659 "Only allow certain ppp modes", "allow modes mode..."}, 660 {"users", "user", AllowUsers, LOCAL_AUTH, 661 "Only allow ppp access to certain users", "allow users logname..."}, 662 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 663 "Display this message", "allow help|? [command]", AllowCommands}, 664 {NULL, NULL, NULL}, 665}; 666 667static struct cmdtab const IfaceCommands[] = 668{ 669 {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 670 "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 671 {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 672 "Add or change an iface address", "iface add! addr[/bits| mask] peer", 673 (void *)1}, 674 {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 675 "Clear iface address(es)", "iface clear"}, 676 {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 677 "Delete iface address", "iface delete addr", NULL}, 678 {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 679 "Delete iface address", "iface delete addr", (void *)1}, 680 {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 681 "Delete iface address", "iface delete addr", (void *)1}, 682 {"show", NULL, iface_Show, LOCAL_AUTH, 683 "Show iface address(es)", "iface show"}, 684 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 685 "Display this message", "nat help|? [command]", IfaceCommands}, 686 {NULL, NULL, NULL}, 687}; 688 689static struct cmdtab const Commands[] = { 690 {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 691 "accept option request", "accept option .."}, 692 {"add", NULL, AddCommand, LOCAL_AUTH, 693 "add route", "add dest mask gateway", NULL}, 694 {NULL, "add!", AddCommand, LOCAL_AUTH, 695 "add or change route", "add! dest mask gateway", (void *)1}, 696 {"allow", "auth", RunListCommand, LOCAL_AUTH, 697 "Allow ppp access", "allow users|modes ....", AllowCommands}, 698 {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 699 "Run a background command", "[!]bg command"}, 700 {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 701 "Clear throughput statistics", 702 "clear ipcp|physical [current|overall|peak]..."}, 703 {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 704 "Clone a link", "clone newname..."}, 705 {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 706 "Close an FSM", "close [lcp|ccp]"}, 707 {"delete", NULL, DeleteCommand, LOCAL_AUTH, 708 "delete route", "delete dest", NULL}, 709 {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 710 "delete a route if it exists", "delete! dest", (void *)1}, 711 {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 712 "Deny option request", "deny option .."}, 713 {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 714 "Dial and login", "dial|call [system ...]", NULL}, 715 {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 716 "Disable option", "disable option .."}, 717 {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 718 "Generate a down event", "down [ccp|lcp]"}, 719 {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 720 "Enable option", "enable option .."}, 721 {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 722 "Set the link identity", "ident text..."}, 723 {"iface", "interface", RunListCommand, LOCAL_AUTH, 724 "interface control", "iface option ...", IfaceCommands}, 725 {"link", "datalink", LinkCommand, LOCAL_AUTH, 726 "Link specific commands", "link name command ..."}, 727 {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 728 "Load settings", "load [system ...]"}, 729#ifndef NONAT 730 {"nat", "alias", RunListCommand, LOCAL_AUTH, 731 "NAT control", "nat option yes|no", NatCommands}, 732#endif 733 {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 734 "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 735 {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 736 "Password for manipulation", "passwd LocalPassword"}, 737 {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 738 "Quit PPP program", "quit|bye [all]"}, 739 {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 740 "Remove a link", "remove"}, 741 {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 742 "Rename a link", "rename name"}, 743 {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 744 "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 745 {"save", NULL, SaveCommand, LOCAL_AUTH, 746 "Save settings", "save"}, 747 {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 748 "Transmit the link identity", "sendident"}, 749 {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 750 "Set parameters", "set[up] var value"}, 751 {"shell", "!", FgShellCommand, LOCAL_AUTH, 752 "Run a subshell", "shell|! [sh command]"}, 753 {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 754 "Show status and stats", "show var"}, 755 {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 756 "Enter terminal mode", "term"}, 757 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 758 "Display this message", "help|? [command]", Commands}, 759 {NULL, NULL, NULL}, 760}; 761 762static int 763ShowEscape(struct cmdargs const *arg) 764{ 765 if (arg->cx->physical->async.cfg.EscMap[32]) { 766 int code, bit; 767 const char *sep = ""; 768 769 for (code = 0; code < 32; code++) 770 if (arg->cx->physical->async.cfg.EscMap[code]) 771 for (bit = 0; bit < 8; bit++) 772 if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 773 prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 774 sep = ", "; 775 } 776 prompt_Printf(arg->prompt, "\n"); 777 } 778 return 0; 779} 780 781static int 782ShowTimerList(struct cmdargs const *arg) 783{ 784 timer_Show(0, arg->prompt); 785 return 0; 786} 787 788static int 789ShowStopped(struct cmdargs const *arg) 790{ 791 prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 792 if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 793 prompt_Printf(arg->prompt, "Disabled"); 794 else 795 prompt_Printf(arg->prompt, "%ld secs", 796 arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 797 798 prompt_Printf(arg->prompt, ", CCP: "); 799 if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 800 prompt_Printf(arg->prompt, "Disabled"); 801 else 802 prompt_Printf(arg->prompt, "%ld secs", 803 arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 804 805 prompt_Printf(arg->prompt, "\n"); 806 807 return 0; 808} 809 810static int 811ShowVersion(struct cmdargs const *arg) 812{ 813 prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 814 return 0; 815} 816 817static int 818ShowProtocolStats(struct cmdargs const *arg) 819{ 820 struct link *l = command_ChooseLink(arg); 821 822 prompt_Printf(arg->prompt, "%s:\n", l->name); 823 link_ReportProtocolStatus(l, arg->prompt); 824 return 0; 825} 826 827static struct cmdtab const ShowCommands[] = { 828 {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 829 "bundle details", "show bundle"}, 830 {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 831 "CCP status", "show cpp"}, 832 {"compress", NULL, sl_Show, LOCAL_AUTH, 833 "VJ compression stats", "show compress"}, 834 {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 835 "escape characters", "show escape"}, 836 {"filter", NULL, filter_Show, LOCAL_AUTH, 837 "packet filters", "show filter [in|out|dial|alive]"}, 838 {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 839 "HDLC errors", "show hdlc"}, 840 {"iface", "interface", iface_Show, LOCAL_AUTH, 841 "Interface status", "show iface"}, 842 {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 843 "IPCP status", "show ipcp"}, 844 {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 845 "Protocol layers", "show layers"}, 846 {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 847 "LCP status", "show lcp"}, 848 {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 849 "(high-level) link info", "show link"}, 850 {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 851 "available link names", "show links"}, 852 {"log", NULL, log_ShowLevel, LOCAL_AUTH, 853 "log levels", "show log"}, 854 {"mem", NULL, mbuf_Show, LOCAL_AUTH, 855 "mbuf allocations", "show mem"}, 856 {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 857 "(low-level) link info", "show physical"}, 858 {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 859 "multilink setup", "show mp"}, 860 {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 861 "protocol summary", "show proto"}, 862 {"route", NULL, route_Show, LOCAL_AUTH, 863 "routing table", "show route"}, 864 {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 865 "STOPPED timeout", "show stopped"}, 866 {"timers", NULL, ShowTimerList, LOCAL_AUTH, 867 "alarm timers", "show timers"}, 868 {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 869 "version string", "show version"}, 870 {"who", NULL, log_ShowWho, LOCAL_AUTH, 871 "client list", "show who"}, 872 {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 873 "Display this message", "show help|? [command]", ShowCommands}, 874 {NULL, NULL, NULL}, 875}; 876 877static struct cmdtab const * 878FindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 879{ 880 int nmatch; 881 int len; 882 struct cmdtab const *found; 883 884 found = NULL; 885 len = strlen(str); 886 nmatch = 0; 887 while (cmds->func) { 888 if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 889 if (cmds->name[len] == '\0') { 890 *pmatch = 1; 891 return cmds; 892 } 893 nmatch++; 894 found = cmds; 895 } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 896 if (cmds->alias[len] == '\0') { 897 *pmatch = 1; 898 return cmds; 899 } 900 nmatch++; 901 found = cmds; 902 } 903 cmds++; 904 } 905 *pmatch = nmatch; 906 return found; 907} 908 909static const char * 910mkPrefix(int argc, char const *const *argv, char *tgt, int sz) 911{ 912 int f, tlen, len; 913 914 tlen = 0; 915 for (f = 0; f < argc && tlen < sz - 2; f++) { 916 if (f) 917 tgt[tlen++] = ' '; 918 len = strlen(argv[f]); 919 if (len > sz - tlen - 1) 920 len = sz - tlen - 1; 921 strncpy(tgt+tlen, argv[f], len); 922 tlen += len; 923 } 924 tgt[tlen] = '\0'; 925 return tgt; 926} 927 928static int 929FindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 930 char const *const *argv, struct prompt *prompt, struct datalink *cx) 931{ 932 struct cmdtab const *cmd; 933 int val = 1; 934 int nmatch; 935 struct cmdargs arg; 936 char prefix[100]; 937 938 cmd = FindCommand(cmds, argv[argn], &nmatch); 939 if (nmatch > 1) 940 log_Printf(LogWARN, "%s: Ambiguous command\n", 941 mkPrefix(argn+1, argv, prefix, sizeof prefix)); 942 else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 943 if ((cmd->lauth & LOCAL_CX) && !cx) 944 /* We've got no context, but we require it */ 945 cx = bundle2datalink(bundle, NULL); 946 947 if ((cmd->lauth & LOCAL_CX) && !cx) 948 log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 949 mkPrefix(argn+1, argv, prefix, sizeof prefix)); 950 else { 951 if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 952 log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 953 mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 954 cx = NULL; 955 } 956 arg.cmdtab = cmds; 957 arg.cmd = cmd; 958 arg.argc = argc; 959 arg.argn = argn+1; 960 arg.argv = argv; 961 arg.bundle = bundle; 962 arg.cx = cx; 963 arg.prompt = prompt; 964 val = (*cmd->func) (&arg); 965 } 966 } else 967 log_Printf(LogWARN, "%s: Invalid command\n", 968 mkPrefix(argn+1, argv, prefix, sizeof prefix)); 969 970 if (val == -1) 971 log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 972 else if (val) 973 log_Printf(LogWARN, "%s: Failed %d\n", 974 mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 975 976 return val; 977} 978 979int 980command_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 981{ 982 char buff2[LINE_LEN-offset]; 983 984 InterpretArg(buff, buff2); 985 strncpy(buff, buff2, LINE_LEN - offset - 1); 986 buff[LINE_LEN - offset - 1] = '\0'; 987 988 return command_Interpret(buff, nb, argv); 989} 990 991int 992command_Interpret(char *buff, int nb, char *argv[MAXARGS]) 993{ 994 char *cp; 995 996 if (nb > 0) { 997 cp = buff + strcspn(buff, "\r\n"); 998 if (cp) 999 *cp = '\0'; 1000 return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 1001 } 1002 return 0; 1003} 1004 1005static int 1006arghidden(int argc, char const *const *argv, int n) 1007{ 1008 /* Is arg n of the given command to be hidden from the log ? */ 1009 1010 /* set authkey xxxxx */ 1011 /* set key xxxxx */ 1012 if (n == 2 && !strncasecmp(argv[0], "se", 2) && 1013 (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 1014 return 1; 1015 1016 /* passwd xxxxx */ 1017 if (n == 1 && !strncasecmp(argv[0], "p", 1)) 1018 return 1; 1019 1020 /* set server port xxxxx .... */ 1021 if (n == 3 && !strncasecmp(argv[0], "se", 2) && 1022 !strncasecmp(argv[1], "se", 2)) 1023 return 1; 1024 1025 return 0; 1026} 1027 1028void 1029command_Run(struct bundle *bundle, int argc, char const *const *argv, 1030 struct prompt *prompt, const char *label, struct datalink *cx) 1031{ 1032 if (argc > 0) { 1033 if (log_IsKept(LogCOMMAND)) { 1034 char buf[LINE_LEN]; 1035 int f, n; 1036 1037 if (label) { 1038 strncpy(buf, label, sizeof buf - 3); 1039 buf[sizeof buf - 3] = '\0'; 1040 strcat(buf, ": "); 1041 n = strlen(buf); 1042 } else { 1043 *buf = '\0'; 1044 n = 0; 1045 } 1046 buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 1047 1048 for (f = 0; f < argc; f++) { 1049 if (n < sizeof buf - 1 && f) 1050 buf[n++] = ' '; 1051 if (arghidden(argc, argv, f)) 1052 strncpy(buf+n, "********", sizeof buf - n - 1); 1053 else 1054 strncpy(buf+n, argv[f], sizeof buf - n - 1); 1055 n += strlen(buf+n); 1056 } 1057 log_Printf(LogCOMMAND, "%s\n", buf); 1058 } 1059 FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 1060 } 1061} 1062 1063int 1064command_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 1065 const char *label) 1066{ 1067 int argc; 1068 char *argv[MAXARGS]; 1069 1070 if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 1071 return 0; 1072 1073 command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 1074 return 1; 1075} 1076 1077static int 1078ShowCommand(struct cmdargs const *arg) 1079{ 1080 if (!arg->prompt) 1081 log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 1082 else if (arg->argc > arg->argn) 1083 FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 1084 arg->prompt, arg->cx); 1085 else 1086 prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 1087 1088 return 0; 1089} 1090 1091static int 1092TerminalCommand(struct cmdargs const *arg) 1093{ 1094 if (!arg->prompt) { 1095 log_Printf(LogWARN, "term: Need a prompt\n"); 1096 return 1; 1097 } 1098 1099 if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 1100 prompt_Printf(arg->prompt, "LCP state is [%s]\n", 1101 State2Nam(arg->cx->physical->link.lcp.fsm.state)); 1102 return 1; 1103 } 1104 1105 datalink_Up(arg->cx, 0, 0); 1106 prompt_TtyTermMode(arg->prompt, arg->cx); 1107 return 0; 1108} 1109 1110static int 1111QuitCommand(struct cmdargs const *arg) 1112{ 1113 if (!arg->prompt || prompt_IsController(arg->prompt) || 1114 (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 1115 (arg->prompt->auth & LOCAL_AUTH))) 1116 Cleanup(EX_NORMAL); 1117 if (arg->prompt) 1118 prompt_Destroy(arg->prompt, 1); 1119 1120 return 0; 1121} 1122 1123static int 1124OpenCommand(struct cmdargs const *arg) 1125{ 1126 if (arg->argc == arg->argn) 1127 bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 1128 else if (arg->argc == arg->argn + 1) { 1129 if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 1130 struct datalink *cx = arg->cx ? 1131 arg->cx : bundle2datalink(arg->bundle, NULL); 1132 if (cx) { 1133 if (cx->physical->link.lcp.fsm.state == ST_OPENED) 1134 fsm_Reopen(&cx->physical->link.lcp.fsm); 1135 else 1136 bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 1137 } else 1138 log_Printf(LogWARN, "open lcp: You must specify a link\n"); 1139 } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 1140 struct fsm *fp; 1141 1142 fp = &command_ChooseLink(arg)->ccp.fsm; 1143 if (fp->link->lcp.fsm.state != ST_OPENED) 1144 log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 1145 else if (fp->state == ST_OPENED) 1146 fsm_Reopen(fp); 1147 else { 1148 fp->open_mode = 0; /* Not passive any more */ 1149 if (fp->state == ST_STOPPED) { 1150 fsm_Down(fp); 1151 fsm_Up(fp); 1152 } else { 1153 fsm_Up(fp); 1154 fsm_Open(fp); 1155 } 1156 } 1157 } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 1158 if (arg->cx) 1159 log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 1160 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 1161 fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 1162 else 1163 bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 1164 } else 1165 return -1; 1166 } else 1167 return -1; 1168 1169 return 0; 1170} 1171 1172static int 1173CloseCommand(struct cmdargs const *arg) 1174{ 1175 if (arg->argc == arg->argn) 1176 bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 1177 else if (arg->argc == arg->argn + 1) { 1178 if (!strcasecmp(arg->argv[arg->argn], "lcp")) 1179 bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 1180 else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 1181 !strcasecmp(arg->argv[arg->argn], "ccp!")) { 1182 struct fsm *fp; 1183 1184 fp = &command_ChooseLink(arg)->ccp.fsm; 1185 if (fp->state == ST_OPENED) { 1186 fsm_Close(fp); 1187 if (arg->argv[arg->argn][3] == '!') 1188 fp->open_mode = 0; /* Stay ST_CLOSED */ 1189 else 1190 fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 1191 } 1192 } else 1193 return -1; 1194 } else 1195 return -1; 1196 1197 return 0; 1198} 1199 1200static int 1201DownCommand(struct cmdargs const *arg) 1202{ 1203 if (arg->argc == arg->argn) { 1204 if (arg->cx) 1205 datalink_Down(arg->cx, CLOSE_STAYDOWN); 1206 else 1207 bundle_Down(arg->bundle, CLOSE_STAYDOWN); 1208 } else if (arg->argc == arg->argn + 1) { 1209 if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 1210 if (arg->cx) 1211 datalink_Down(arg->cx, CLOSE_LCP); 1212 else 1213 bundle_Down(arg->bundle, CLOSE_LCP); 1214 } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 1215 struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 1216 &arg->bundle->ncp.mp.link.ccp.fsm; 1217 fsm2initial(fp); 1218 } else 1219 return -1; 1220 } else 1221 return -1; 1222 1223 return 0; 1224} 1225 1226static int 1227SetModemSpeed(struct cmdargs const *arg) 1228{ 1229 long speed; 1230 char *end; 1231 1232 if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 1233 if (arg->argc > arg->argn+1) { 1234 log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 1235 return -1; 1236 } 1237 if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 1238 physical_SetSync(arg->cx->physical); 1239 return 0; 1240 } 1241 end = NULL; 1242 speed = strtol(arg->argv[arg->argn], &end, 10); 1243 if (*end) { 1244 log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 1245 arg->argv[arg->argn]); 1246 return -1; 1247 } 1248 if (physical_SetSpeed(arg->cx->physical, speed)) 1249 return 0; 1250 log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 1251 } else 1252 log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 1253 1254 return -1; 1255} 1256 1257static int 1258SetStoppedTimeout(struct cmdargs const *arg) 1259{ 1260 struct link *l = &arg->cx->physical->link; 1261 1262 l->lcp.fsm.StoppedTimer.load = 0; 1263 l->ccp.fsm.StoppedTimer.load = 0; 1264 if (arg->argc <= arg->argn+2) { 1265 if (arg->argc > arg->argn) { 1266 l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 1267 if (arg->argc > arg->argn+1) 1268 l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 1269 } 1270 return 0; 1271 } 1272 return -1; 1273} 1274 1275static int 1276SetServer(struct cmdargs const *arg) 1277{ 1278 int res = -1; 1279 1280 if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 1281 const char *port, *passwd, *mask; 1282 int mlen; 1283 1284 /* What's what ? */ 1285 port = arg->argv[arg->argn]; 1286 if (arg->argc == arg->argn + 2) { 1287 passwd = arg->argv[arg->argn+1]; 1288 mask = NULL; 1289 } else if (arg->argc == arg->argn + 3) { 1290 passwd = arg->argv[arg->argn+1]; 1291 mask = arg->argv[arg->argn+2]; 1292 mlen = strlen(mask); 1293 if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 1294 (mlen == 4 && *mask != '0')) { 1295 log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 1296 arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 1297 return -1; 1298 } 1299 } else if (arg->argc != arg->argn + 1) 1300 return -1; 1301 else if (strcasecmp(port, "none") == 0) { 1302 if (server_Clear(arg->bundle)) 1303 log_Printf(LogPHASE, "Disabled server socket\n"); 1304 return 0; 1305 } else if (strcasecmp(port, "open") == 0) { 1306 switch (server_Reopen(arg->bundle)) { 1307 case SERVER_OK: 1308 return 0; 1309 case SERVER_FAILED: 1310 log_Printf(LogWARN, "Failed to reopen server port\n"); 1311 return 1; 1312 case SERVER_UNSET: 1313 log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 1314 return 1; 1315 default: 1316 break; 1317 } 1318 return -1; 1319 } else if (strcasecmp(port, "closed") == 0) { 1320 if (server_Close(arg->bundle)) 1321 log_Printf(LogPHASE, "Closed server socket\n"); 1322 else 1323 log_Printf(LogWARN, "Server socket not open\n"); 1324 1325 return 0; 1326 } else 1327 return -1; 1328 1329 strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 1330 server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 1331 1332 if (*port == '/') { 1333 mode_t imask; 1334 char *ptr, name[LINE_LEN + 12]; 1335 1336 if (mask == NULL) 1337 imask = (mode_t)-1; 1338 else for (imask = mlen = 0; mask[mlen]; mlen++) 1339 imask = (imask * 8) + mask[mlen] - '0'; 1340 1341 ptr = strstr(port, "%d"); 1342 if (ptr) { 1343 snprintf(name, sizeof name, "%.*s%d%s", 1344 (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 1345 port = name; 1346 } 1347 res = server_LocalOpen(arg->bundle, port, imask); 1348 } else { 1349 int iport, add = 0; 1350 1351 if (mask != NULL) 1352 return -1; 1353 1354 if (*port == '+') { 1355 port++; 1356 add = 1; 1357 } 1358 if (strspn(port, "0123456789") != strlen(port)) { 1359 struct servent *s; 1360 1361 if ((s = getservbyname(port, "tcp")) == NULL) { 1362 iport = 0; 1363 log_Printf(LogWARN, "%s: Invalid port or service\n", port); 1364 } else 1365 iport = ntohs(s->s_port); 1366 } else 1367 iport = atoi(port); 1368 1369 if (iport) { 1370 if (add) 1371 iport += arg->bundle->unit; 1372 res = server_TcpOpen(arg->bundle, iport); 1373 } else 1374 res = -1; 1375 } 1376 } 1377 1378 return res; 1379} 1380 1381static int 1382SetEscape(struct cmdargs const *arg) 1383{ 1384 int code; 1385 int argc = arg->argc - arg->argn; 1386 char const *const *argv = arg->argv + arg->argn; 1387 1388 for (code = 0; code < 33; code++) 1389 arg->cx->physical->async.cfg.EscMap[code] = 0; 1390 1391 while (argc-- > 0) { 1392 sscanf(*argv++, "%x", &code); 1393 code &= 0xff; 1394 arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 1395 arg->cx->physical->async.cfg.EscMap[32] = 1; 1396 } 1397 return 0; 1398} 1399 1400static int 1401SetInterfaceAddr(struct cmdargs const *arg) 1402{ 1403 struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 1404 const char *hisaddr; 1405 1406 if (arg->argc > arg->argn + 4) 1407 return -1; 1408 1409 hisaddr = NULL; 1410 memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 1411 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1412 ipcp->cfg.HaveTriggerAddress = 0; 1413 ipcp->cfg.netmask.s_addr = INADDR_ANY; 1414 iplist_reset(&ipcp->cfg.peer_list); 1415 1416 if (arg->argc > arg->argn) { 1417 if (!ParseAddr(ipcp, arg->argv[arg->argn], 1418 &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 1419 &ipcp->cfg.my_range.width)) 1420 return 1; 1421 if (arg->argc > arg->argn+1) { 1422 hisaddr = arg->argv[arg->argn+1]; 1423 if (arg->argc > arg->argn+2) { 1424 ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 1425 if (arg->argc > arg->argn+3) { 1426 ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 1427 ipcp->cfg.HaveTriggerAddress = 1; 1428 } 1429 } 1430 } 1431 } 1432 1433 /* 0.0.0.0 means any address (0 bits) */ 1434 if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 1435 ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 1436 ipcp->cfg.my_range.width = 0; 1437 } 1438 ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 1439 bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 1440 1441 if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 1442 arg->bundle->phys_type.all & PHYS_AUTO)) 1443 return 4; 1444 1445 return 0; 1446} 1447 1448static int 1449SetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 1450 u_int *maxtrm, int def) 1451{ 1452 if (argc == 0) { 1453 *timeout = DEF_FSMRETRY; 1454 *maxreq = def; 1455 if (maxtrm != NULL) 1456 *maxtrm = def; 1457 } else { 1458 long l = atol(argv[0]); 1459 1460 if (l < MIN_FSMRETRY) { 1461 log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 1462 l, MIN_FSMRETRY); 1463 return 1; 1464 } else 1465 *timeout = l; 1466 1467 if (argc > 1) { 1468 l = atol(argv[1]); 1469 if (l < 1) { 1470 log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 1471 l = 1; 1472 } 1473 *maxreq = l; 1474 1475 if (argc > 2 && maxtrm != NULL) { 1476 l = atol(argv[2]); 1477 if (l < 1) { 1478 log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 1479 l = 1; 1480 } 1481 *maxtrm = l; 1482 } 1483 } 1484 } 1485 1486 return 0; 1487} 1488 1489static int 1490SetVariable(struct cmdargs const *arg) 1491{ 1492 long long_val, param = (long)arg->cmd->args; 1493 int mode, dummyint, f, first, res; 1494 u_short *change; 1495 const char *argp; 1496 struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 1497 struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 1498 struct in_addr dummyaddr, *addr; 1499 1500 if (arg->argc > arg->argn) 1501 argp = arg->argv[arg->argn]; 1502 else 1503 argp = ""; 1504 1505 res = 0; 1506 1507 if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 1508 log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 1509 arg->cmd->name); 1510 return 1; 1511 } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 1512 log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 1513 arg->cmd->name, cx->name); 1514 cx = NULL; 1515 } 1516 1517 switch (param) { 1518 case VAR_AUTHKEY: 1519 strncpy(arg->bundle->cfg.auth.key, argp, 1520 sizeof arg->bundle->cfg.auth.key - 1); 1521 arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 1522 break; 1523 1524 case VAR_AUTHNAME: 1525 switch (bundle_Phase(arg->bundle)) { 1526 default: 1527 log_Printf(LogWARN, "Altering authname while at phase %s\n", 1528 bundle_PhaseName(arg->bundle)); 1529 /* drop through */ 1530 case PHASE_DEAD: 1531 case PHASE_ESTABLISH: 1532 strncpy(arg->bundle->cfg.auth.name, argp, 1533 sizeof arg->bundle->cfg.auth.name - 1); 1534 arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 1535 break; 1536 } 1537 break; 1538 1539 case VAR_AUTOLOAD: 1540 if (arg->argc == arg->argn + 3) { 1541 int v1, v2, v3; 1542 char *end; 1543 1544 v1 = strtol(arg->argv[arg->argn], &end, 0); 1545 if (v1 < 0 || *end) { 1546 log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 1547 arg->argv[arg->argn]); 1548 res = 1; 1549 break; 1550 } 1551 1552 v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 1553 if (v2 < 0 || *end) { 1554 log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 1555 arg->argv[arg->argn + 1]); 1556 res = 1; 1557 break; 1558 } 1559 if (v2 < v1) { 1560 v3 = v1; 1561 v1 = v2; 1562 v2 = v3; 1563 } 1564 1565 v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 1566 if (v3 <= 0 || *end) { 1567 log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 1568 arg->argv[arg->argn + 2]); 1569 res = 1; 1570 break; 1571 } 1572 1573 arg->bundle->ncp.mp.cfg.autoload.min = v1; 1574 arg->bundle->ncp.mp.cfg.autoload.max = v2; 1575 arg->bundle->ncp.mp.cfg.autoload.period = v3; 1576 mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 1577 } else { 1578 log_Printf(LogWARN, "Set autoload requires three arguments\n"); 1579 res = 1; 1580 } 1581 break; 1582 1583 case VAR_DIAL: 1584 strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 1585 cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 1586 break; 1587 1588 case VAR_LOGIN: 1589 strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 1590 cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 1591 break; 1592 1593 case VAR_WINSIZE: 1594 if (arg->argc > arg->argn) { 1595 l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 1596 if (l->ccp.cfg.deflate.out.winsize < 8 || 1597 l->ccp.cfg.deflate.out.winsize > 15) { 1598 log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 1599 l->ccp.cfg.deflate.out.winsize); 1600 l->ccp.cfg.deflate.out.winsize = 15; 1601 } 1602 if (arg->argc > arg->argn+1) { 1603 l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 1604 if (l->ccp.cfg.deflate.in.winsize < 8 || 1605 l->ccp.cfg.deflate.in.winsize > 15) { 1606 log_Printf(LogWARN, "%d: Invalid incoming window size\n", 1607 l->ccp.cfg.deflate.in.winsize); 1608 l->ccp.cfg.deflate.in.winsize = 15; 1609 } 1610 } else 1611 l->ccp.cfg.deflate.in.winsize = 0; 1612 } else { 1613 log_Printf(LogWARN, "No window size specified\n"); 1614 res = 1; 1615 } 1616 break; 1617 1618#ifdef HAVE_DES 1619 case VAR_MPPE: 1620 if (arg->argc > arg->argn + 2) { 1621 res = -1; 1622 break; 1623 } 1624 1625 if (arg->argc == arg->argn) { 1626 l->ccp.cfg.mppe.keybits = 0; 1627 l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 1628 l->ccp.cfg.mppe.required = 0; 1629 break; 1630 } 1631 1632 if (!strcmp(argp, "*")) 1633 long_val = 0; 1634 else { 1635 long_val = atol(argp); 1636 if (long_val != 40 && long_val != 56 && long_val != 128) { 1637 log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 1638 res = -1; 1639 break; 1640 } 1641 } 1642 1643 if (arg->argc == arg->argn + 2) { 1644 if (!strcmp(arg->argv[arg->argn + 1], "*")) 1645 l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 1646 else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 1647 l->ccp.cfg.mppe.state = MPPE_STATELESS; 1648 else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 1649 l->ccp.cfg.mppe.state = MPPE_STATEFUL; 1650 else { 1651 log_Printf(LogWARN, "%s: Invalid state value\n", 1652 arg->argv[arg->argn + 1]); 1653 res = -1; 1654 break; 1655 } 1656 } else 1657 l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 1658 l->ccp.cfg.mppe.keybits = long_val; 1659 l->ccp.cfg.mppe.required = 1; 1660 break; 1661#endif 1662 1663 case VAR_DEVICE: 1664 physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 1665 arg->argv + arg->argn); 1666 break; 1667 1668 case VAR_ACCMAP: 1669 if (arg->argc > arg->argn) { 1670 u_long ulong_val; 1671 sscanf(argp, "%lx", &ulong_val); 1672 cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 1673 } else { 1674 log_Printf(LogWARN, "No accmap specified\n"); 1675 res = 1; 1676 } 1677 break; 1678 1679 case VAR_MODE: 1680 mode = Nam2mode(argp); 1681 if (mode == PHYS_NONE || mode == PHYS_ALL) { 1682 log_Printf(LogWARN, "%s: Invalid mode\n", argp); 1683 res = -1; 1684 break; 1685 } 1686 bundle_SetMode(arg->bundle, cx, mode); 1687 break; 1688 1689 case VAR_MRRU: 1690 switch (bundle_Phase(arg->bundle)) { 1691 case PHASE_DEAD: 1692 break; 1693 case PHASE_ESTABLISH: 1694 /* Make sure none of our links are DATALINK_LCP or greater */ 1695 if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 1696 log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 1697 res = 1; 1698 break; 1699 } 1700 break; 1701 default: 1702 log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 1703 res = 1; 1704 break; 1705 } 1706 if (res != 0) 1707 break; 1708 long_val = atol(argp); 1709 if (long_val && long_val < MIN_MRU) { 1710 log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 1711 res = 1; 1712 break; 1713 } else if (long_val > MAX_MRU) { 1714 log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 1715 res = 1; 1716 break; 1717 } else 1718 arg->bundle->ncp.mp.cfg.mrru = long_val; 1719 break; 1720 1721 case VAR_MRU: 1722 long_val = 0; /* silence gcc */ 1723 change = NULL; /* silence gcc */ 1724 switch(arg->argc - arg->argn) { 1725 case 1: 1726 if (argp[strspn(argp, "0123456789")] != '\0') { 1727 res = -1; 1728 break; 1729 } 1730 /*FALLTHRU*/ 1731 case 0: 1732 long_val = atol(argp); 1733 change = &l->lcp.cfg.mru; 1734 if (long_val > l->lcp.cfg.max_mru) { 1735 log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 1736 l->lcp.cfg.max_mru); 1737 res = 1; 1738 break; 1739 } 1740 break; 1741 case 2: 1742 if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 1743 res = -1; 1744 break; 1745 } 1746 long_val = atol(arg->argv[arg->argn + 1]); 1747 change = &l->lcp.cfg.max_mru; 1748 if (long_val > MAX_MRU) { 1749 log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 1750 MAX_MRU); 1751 res = 1; 1752 break; 1753 } 1754 break; 1755 default: 1756 res = -1; 1757 break; 1758 } 1759 if (res != 0) 1760 break; 1761 1762 if (long_val == 0) 1763 *change = DEF_MRU; 1764 else if (long_val < MIN_MRU) { 1765 log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 1766 res = 1; 1767 break; 1768 } else if (long_val > MAX_MRU) { 1769 log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 1770 res = 1; 1771 break; 1772 } else 1773 *change = long_val; 1774 if (l->lcp.cfg.mru > *change) 1775 l->lcp.cfg.mru = *change; 1776 break; 1777 1778 case VAR_MTU: 1779 long_val = 0; /* silence gcc */ 1780 change = NULL; /* silence gcc */ 1781 switch(arg->argc - arg->argn) { 1782 case 1: 1783 if (argp[strspn(argp, "0123456789")] != '\0') { 1784 res = -1; 1785 break; 1786 } 1787 /*FALLTHRU*/ 1788 case 0: 1789 long_val = atol(argp); 1790 change = &l->lcp.cfg.mtu; 1791 if (long_val > l->lcp.cfg.max_mtu) { 1792 log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 1793 l->lcp.cfg.max_mtu); 1794 res = 1; 1795 break; 1796 } 1797 break; 1798 case 2: 1799 if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 1800 res = -1; 1801 break; 1802 } 1803 long_val = atol(arg->argv[arg->argn + 1]); 1804 change = &l->lcp.cfg.max_mtu; 1805 if (long_val > MAX_MTU) { 1806 log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 1807 MAX_MTU); 1808 res = 1; 1809 break; 1810 } 1811 break; 1812 default: 1813 res = -1; 1814 break; 1815 } 1816 1817 if (res != 0) 1818 break; 1819 1820 if (long_val && long_val < MIN_MTU) { 1821 log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 1822 res = 1; 1823 break; 1824 } else if (long_val > MAX_MTU) { 1825 log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 1826 res = 1; 1827 break; 1828 } else 1829 *change = long_val; 1830 if (l->lcp.cfg.mtu > *change) 1831 l->lcp.cfg.mtu = *change; 1832 break; 1833 1834 case VAR_OPENMODE: 1835 if (strcasecmp(argp, "active") == 0) 1836 cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 1837 atoi(arg->argv[arg->argn+1]) : 1; 1838 else if (strcasecmp(argp, "passive") == 0) 1839 cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 1840 else { 1841 log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 1842 res = 1; 1843 } 1844 break; 1845 1846 case VAR_PHONE: 1847 strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 1848 cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 1849 cx->phone.alt = cx->phone.next = NULL; 1850 break; 1851 1852 case VAR_HANGUP: 1853 strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 1854 cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 1855 break; 1856 1857 case VAR_IFQUEUE: 1858 long_val = atol(argp); 1859 arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 1860 break; 1861 1862 case VAR_LOGOUT: 1863 strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 1864 cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 1865 break; 1866 1867 case VAR_IDLETIMEOUT: 1868 if (arg->argc > arg->argn+2) { 1869 log_Printf(LogWARN, "Too many idle timeout values\n"); 1870 res = 1; 1871 } else if (arg->argc == arg->argn) { 1872 log_Printf(LogWARN, "Too few idle timeout values\n"); 1873 res = 1; 1874 } else { 1875 int timeout, min; 1876 1877 timeout = atoi(argp); 1878 min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 1879 bundle_SetIdleTimer(arg->bundle, timeout, min); 1880 } 1881 break; 1882 1883 case VAR_LQRPERIOD: 1884 long_val = atol(argp); 1885 if (long_val < MIN_LQRPERIOD) { 1886 log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 1887 long_val, MIN_LQRPERIOD); 1888 res = 1; 1889 } else 1890 l->lcp.cfg.lqrperiod = long_val; 1891 break; 1892 1893 case VAR_LCPRETRY: 1894 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1895 &cx->physical->link.lcp.cfg.fsm.timeout, 1896 &cx->physical->link.lcp.cfg.fsm.maxreq, 1897 &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 1898 break; 1899 1900 case VAR_CHAPRETRY: 1901 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1902 &cx->chap.auth.cfg.fsm.timeout, 1903 &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 1904 break; 1905 1906 case VAR_PAPRETRY: 1907 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1908 &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 1909 NULL, DEF_FSMAUTHTRIES); 1910 break; 1911 1912 case VAR_CCPRETRY: 1913 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1914 &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 1915 &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 1916 break; 1917 1918 case VAR_IPCPRETRY: 1919 res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 1920 &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 1921 &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 1922 &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 1923 break; 1924 1925 case VAR_NBNS: 1926 case VAR_DNS: 1927 if (param == VAR_DNS) { 1928 addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 1929 addr[0].s_addr = addr[1].s_addr = INADDR_NONE; 1930 } else { 1931 addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 1932 addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1933 } 1934 1935 if (arg->argc > arg->argn) { 1936 ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 1937 addr, &dummyaddr, &dummyint); 1938 if (arg->argc > arg->argn+1) 1939 ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 1940 addr + 1, &dummyaddr, &dummyint); 1941 1942 if (addr[0].s_addr == INADDR_ANY) { 1943 addr[0].s_addr = addr[1].s_addr; 1944 addr[1].s_addr = INADDR_ANY; 1945 } 1946 if (addr[0].s_addr == INADDR_NONE) { 1947 addr[0].s_addr = addr[1].s_addr; 1948 addr[1].s_addr = INADDR_NONE; 1949 } 1950 } 1951 break; 1952 1953 case VAR_CALLBACK: 1954 cx->cfg.callback.opmask = 0; 1955 for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 1956 if (!strcasecmp(arg->argv[dummyint], "auth")) 1957 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 1958 else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 1959 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 1960 else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 1961 if (dummyint == arg->argc - 1) 1962 log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 1963 else { 1964 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 1965 strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 1966 sizeof cx->cfg.callback.msg - 1); 1967 cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 1968 } 1969 } else if (!strcasecmp(arg->argv[dummyint], "none")) 1970 cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 1971 else { 1972 res = -1; 1973 break; 1974 } 1975 } 1976 if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 1977 cx->cfg.callback.opmask = 0; 1978 break; 1979 1980 case VAR_CBCP: 1981 cx->cfg.cbcp.delay = 0; 1982 *cx->cfg.cbcp.phone = '\0'; 1983 cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 1984 if (arg->argc > arg->argn) { 1985 strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 1986 sizeof cx->cfg.cbcp.phone - 1); 1987 cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 1988 if (arg->argc > arg->argn + 1) { 1989 cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 1990 if (arg->argc > arg->argn + 2) { 1991 long_val = atol(arg->argv[arg->argn + 2]); 1992 if (long_val < MIN_FSMRETRY) 1993 log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 1994 long_val, MIN_FSMRETRY); 1995 else 1996 cx->cfg.cbcp.fsmretry = long_val; 1997 } 1998 } 1999 } 2000 break; 2001 2002 case VAR_CHOKED: 2003 arg->bundle->cfg.choked.timeout = atoi(argp); 2004 if (arg->bundle->cfg.choked.timeout <= 0) 2005 arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 2006 break; 2007 2008 case VAR_SENDPIPE: 2009 long_val = atol(argp); 2010 arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 2011 break; 2012 2013 case VAR_RECVPIPE: 2014 long_val = atol(argp); 2015 arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 2016 break; 2017 2018#ifndef NORADIUS 2019 case VAR_RADIUS: 2020 if (!*argp) 2021 *arg->bundle->radius.cfg.file = '\0'; 2022 else if (access(argp, R_OK)) { 2023 log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 2024 res = 1; 2025 break; 2026 } else { 2027 strncpy(arg->bundle->radius.cfg.file, argp, 2028 sizeof arg->bundle->radius.cfg.file - 1); 2029 arg->bundle->radius.cfg.file 2030 [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 2031 } 2032 break; 2033#endif 2034 2035 case VAR_CD: 2036 if (*argp) { 2037 if (strcasecmp(argp, "off")) { 2038 long_val = atol(argp); 2039 if (long_val < 0) 2040 long_val = 0; 2041 cx->physical->cfg.cd.delay = long_val; 2042 cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 2043 CD_REQUIRED : CD_VARIABLE; 2044 } else 2045 cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 2046 } else { 2047 cx->physical->cfg.cd.delay = 0; 2048 cx->physical->cfg.cd.necessity = CD_DEFAULT; 2049 } 2050 break; 2051 2052 case VAR_PARITY: 2053 if (arg->argc == arg->argn + 1) 2054 res = physical_SetParity(arg->cx->physical, argp); 2055 else { 2056 log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 2057 res = 1; 2058 } 2059 break; 2060 2061 case VAR_CRTSCTS: 2062 if (strcasecmp(argp, "on") == 0) 2063 physical_SetRtsCts(arg->cx->physical, 1); 2064 else if (strcasecmp(argp, "off") == 0) 2065 physical_SetRtsCts(arg->cx->physical, 0); 2066 else { 2067 log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 2068 res = 1; 2069 } 2070 break; 2071 2072 case VAR_URGENTPORTS: 2073 if (arg->argn == arg->argc) { 2074 ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 2075 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2076 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2077 } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 2078 ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 2079 if (arg->argn == arg->argc - 1) 2080 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2081 else for (f = arg->argn + 1; f < arg->argc; f++) 2082 if (*arg->argv[f] == '+') 2083 ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 2084 else if (*arg->argv[f] == '-') 2085 ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp, 2086 atoi(arg->argv[f] + 1)); 2087 else { 2088 if (f == arg->argn) 2089 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2090 ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 2091 } 2092 } else if (arg->argn == arg->argc - 1 && 2093 !strcasecmp(arg->argv[arg->argn], "none")) { 2094 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2095 ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 2096 ipcp_ClearUrgentTOS(&arg->bundle->ncp.ipcp); 2097 } else { 2098 ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 2099 first = arg->argn; 2100 if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 2101 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2102 2103 for (f = first; f < arg->argc; f++) 2104 if (*arg->argv[f] == '+') 2105 ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 2106 else if (*arg->argv[f] == '-') 2107 ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp, 2108 atoi(arg->argv[f] + 1)); 2109 else { 2110 if (f == first) 2111 ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 2112 ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 2113 } 2114 } 2115 break; 2116 } 2117 2118 return res; 2119} 2120 2121static struct cmdtab const SetCommands[] = { 2122 {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2123 "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 2124 {"authkey", "key", SetVariable, LOCAL_AUTH, 2125 "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 2126 {"authname", NULL, SetVariable, LOCAL_AUTH, 2127 "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 2128 {"autoload", NULL, SetVariable, LOCAL_AUTH, 2129 "auto link [de]activation", "set autoload maxtime maxload mintime minload", 2130 (const void *)VAR_AUTOLOAD}, 2131 {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 2132 "datalink bandwidth", "set bandwidth value"}, 2133 {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2134 "callback control", "set callback [none|auth|cbcp|" 2135 "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 2136 {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2137 "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 2138 (const void *)VAR_CBCP}, 2139 {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2140 "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 2141 {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 2142 "set cd value[!]", (const void *)VAR_CD}, 2143 {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 2144 "CHAP retries", "set chapretry value [attempts]", 2145 (const void *)VAR_CHAPRETRY}, 2146 {"choked", NULL, SetVariable, LOCAL_AUTH, 2147 "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 2148 {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 2149 "Use hardware flow control", "set ctsrts [on|off]", 2150 (const char *)VAR_CRTSCTS}, 2151 {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2152 "deflate window sizes", "set deflate out-winsize in-winsize", 2153 (const void *) VAR_WINSIZE}, 2154#ifdef HAVE_DES 2155 {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2156 "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 2157 (const void *) VAR_MPPE}, 2158#endif 2159 {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 2160 "physical device name", "set device|line device-name[,device-name]", 2161 (const void *) VAR_DEVICE}, 2162 {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2163 "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 2164 {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 2165 "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 2166 {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 2167 "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 2168 {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 2169 "escape characters", "set escape hex-digit ..."}, 2170 {"filter", NULL, filter_Set, LOCAL_AUTH, 2171 "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 2172 "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 2173 "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 2174 {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2175 "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 2176 {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 2177 "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 2178 {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 2179 "set ifqueue packets", (const void *)VAR_IFQUEUE}, 2180 {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 2181 "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 2182 {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 2183 "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 2184 {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 2185 "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 2186 "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 2187 {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2188 "login script", "set login chat-script", (const void *) VAR_LOGIN}, 2189 {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2190 "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 2191 {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2192 "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 2193 {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 2194 "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 2195 {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 2196 "set mrru value", (const void *)VAR_MRRU}, 2197 {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2198 "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 2199 {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2200 "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 2201 {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 2202 "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 2203 {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 2204 "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 2205 {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 2206 "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 2207 {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 2208 "set parity [odd|even|none]", (const void *)VAR_PARITY}, 2209 {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 2210 "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 2211 {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 2212 "Process title", "set proctitle [value]"}, 2213#ifndef NORADIUS 2214 {"radius", NULL, SetVariable, LOCAL_AUTH, 2215 "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 2216#endif 2217 {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 2218 "Reconnect timeout", "set reconnect value ntries"}, 2219 {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 2220 "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 2221 {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 2222 "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 2223 {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 2224 "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 2225 {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 2226 "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 2227 {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 2228 "physical speed", "set speed value|sync"}, 2229 {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 2230 "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 2231 {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 2232 "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 2233 {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 2234 "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 2235 {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 2236 "vj values", "set vj slots|slotcomp [value]"}, 2237 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 2238 "Display this message", "set help|? [command]", SetCommands}, 2239 {NULL, NULL, NULL}, 2240}; 2241 2242static int 2243SetCommand(struct cmdargs const *arg) 2244{ 2245 if (arg->argc > arg->argn) 2246 FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 2247 arg->prompt, arg->cx); 2248 else if (arg->prompt) 2249 prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 2250 " syntax help.\n"); 2251 else 2252 log_Printf(LogWARN, "set command must have arguments\n"); 2253 2254 return 0; 2255} 2256 2257static int 2258AddCommand(struct cmdargs const *arg) 2259{ 2260 struct in_addr dest, gateway, netmask; 2261 int gw, addrs; 2262 2263 if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 2264 return -1; 2265 2266 addrs = 0; 2267 if (arg->argc == arg->argn+2) { 2268 if (!strcasecmp(arg->argv[arg->argn], "default")) 2269 dest.s_addr = netmask.s_addr = INADDR_ANY; 2270 else { 2271 int width; 2272 2273 if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 2274 &dest, &netmask, &width)) 2275 return -1; 2276 if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 2277 addrs = ROUTE_DSTMYADDR; 2278 else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 2279 addrs = ROUTE_DSTHISADDR; 2280 else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 2281 addrs = ROUTE_DSTDNS0; 2282 else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 2283 addrs = ROUTE_DSTDNS1; 2284 } 2285 gw = 1; 2286 } else { 2287 if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 2288 addrs = ROUTE_DSTMYADDR; 2289 dest = arg->bundle->ncp.ipcp.my_ip; 2290 } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 2291 addrs = ROUTE_DSTHISADDR; 2292 dest = arg->bundle->ncp.ipcp.peer_ip; 2293 } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 2294 addrs = ROUTE_DSTDNS0; 2295 dest = arg->bundle->ncp.ipcp.ns.dns[0]; 2296 } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 2297 addrs = ROUTE_DSTDNS1; 2298 dest = arg->bundle->ncp.ipcp.ns.dns[1]; 2299 } else { 2300 dest = GetIpAddr(arg->argv[arg->argn]); 2301 if (dest.s_addr == INADDR_NONE) { 2302 log_Printf(LogWARN, "%s: Invalid destination address\n", 2303 arg->argv[arg->argn]); 2304 return -1; 2305 } 2306 } 2307 netmask = GetIpAddr(arg->argv[arg->argn+1]); 2308 gw = 2; 2309 } 2310 2311 if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 2312 gateway = arg->bundle->ncp.ipcp.peer_ip; 2313 addrs |= ROUTE_GWHISADDR; 2314 } else { 2315 gateway = GetIpAddr(arg->argv[arg->argn+gw]); 2316 if (gateway.s_addr == INADDR_NONE) { 2317 log_Printf(LogWARN, "%s: Invalid gateway address\n", 2318 arg->argv[arg->argn + gw]); 2319 return -1; 2320 } 2321 } 2322 2323 if (rt_Set(arg->bundle, RTM_ADD, dest, gateway, netmask, 2324 arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 2325 && addrs != ROUTE_STATIC) 2326 route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 2327 2328 return 0; 2329} 2330 2331static int 2332DeleteCommand(struct cmdargs const *arg) 2333{ 2334 struct in_addr dest, none; 2335 int addrs; 2336 2337 if (arg->argc == arg->argn+1) { 2338 if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 2339 route_IfDelete(arg->bundle, 0); 2340 route_DeleteAll(&arg->bundle->ncp.ipcp.route); 2341 } else { 2342 addrs = 0; 2343 if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 2344 dest = arg->bundle->ncp.ipcp.my_ip; 2345 addrs = ROUTE_DSTMYADDR; 2346 } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 2347 dest = arg->bundle->ncp.ipcp.peer_ip; 2348 addrs = ROUTE_DSTHISADDR; 2349 } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 2350 dest = arg->bundle->ncp.ipcp.ns.dns[0]; 2351 addrs = ROUTE_DSTDNS0; 2352 } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 2353 dest = arg->bundle->ncp.ipcp.ns.dns[1]; 2354 addrs = ROUTE_DSTDNS1; 2355 } else { 2356 dest = GetIpAddr(arg->argv[arg->argn]); 2357 if (dest.s_addr == INADDR_NONE) { 2358 log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 2359 return -1; 2360 } 2361 addrs = ROUTE_STATIC; 2362 } 2363 none.s_addr = INADDR_ANY; 2364 rt_Set(arg->bundle, RTM_DELETE, dest, none, none, 2365 arg->cmd->args ? 1 : 0, 0); 2366 route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 2367 } 2368 } else 2369 return -1; 2370 2371 return 0; 2372} 2373 2374#ifndef NONAT 2375static int 2376NatEnable(struct cmdargs const *arg) 2377{ 2378 if (arg->argc == arg->argn+1) { 2379 if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 2380 if (!arg->bundle->NatEnabled) { 2381 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 2382 PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 2383 arg->bundle->NatEnabled = 1; 2384 } 2385 return 0; 2386 } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 2387 arg->bundle->NatEnabled = 0; 2388 arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 2389 /* Don't iface_Clear() - there may be manually configured addresses */ 2390 return 0; 2391 } 2392 } 2393 2394 return -1; 2395} 2396 2397 2398static int 2399NatOption(struct cmdargs const *arg) 2400{ 2401 long param = (long)arg->cmd->args; 2402 2403 if (arg->argc == arg->argn+1) { 2404 if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 2405 if (arg->bundle->NatEnabled) { 2406 PacketAliasSetMode(param, param); 2407 return 0; 2408 } 2409 log_Printf(LogWARN, "nat not enabled\n"); 2410 } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 2411 if (arg->bundle->NatEnabled) { 2412 PacketAliasSetMode(0, param); 2413 return 0; 2414 } 2415 log_Printf(LogWARN, "nat not enabled\n"); 2416 } 2417 } 2418 return -1; 2419} 2420#endif /* #ifndef NONAT */ 2421 2422static int 2423LinkCommand(struct cmdargs const *arg) 2424{ 2425 if (arg->argc > arg->argn+1) { 2426 char namelist[LINE_LEN]; 2427 struct datalink *cx; 2428 char *name; 2429 int result = 0; 2430 2431 if (!strcmp(arg->argv[arg->argn], "*")) { 2432 struct datalink *dl; 2433 2434 cx = arg->bundle->links; 2435 while (cx) { 2436 /* Watch it, the command could be a ``remove'' */ 2437 dl = cx->next; 2438 FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 2439 arg->prompt, cx); 2440 for (cx = arg->bundle->links; cx; cx = cx->next) 2441 if (cx == dl) 2442 break; /* Pointer's still valid ! */ 2443 } 2444 } else { 2445 strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 2446 namelist[sizeof namelist - 1] = '\0'; 2447 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 2448 if (!bundle2datalink(arg->bundle, name)) { 2449 log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 2450 return 1; 2451 } 2452 2453 strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 2454 namelist[sizeof namelist - 1] = '\0'; 2455 for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 2456 cx = bundle2datalink(arg->bundle, name); 2457 if (cx) 2458 FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 2459 arg->prompt, cx); 2460 else { 2461 log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 2462 result++; 2463 } 2464 } 2465 } 2466 return result; 2467 } 2468 2469 log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 2470 return 2; 2471} 2472 2473struct link * 2474command_ChooseLink(struct cmdargs const *arg) 2475{ 2476 if (arg->cx) 2477 return &arg->cx->physical->link; 2478 else if (!arg->bundle->ncp.mp.cfg.mrru) { 2479 struct datalink *dl = bundle2datalink(arg->bundle, NULL); 2480 if (dl) 2481 return &dl->physical->link; 2482 } 2483 return &arg->bundle->ncp.mp.link; 2484} 2485 2486static const char * 2487ident_cmd(const char *cmd, unsigned *keep, unsigned *add) 2488{ 2489 const char *result; 2490 2491 switch (*cmd) { 2492 case 'A': 2493 case 'a': 2494 result = "accept"; 2495 *keep = NEG_MYMASK; 2496 *add = NEG_ACCEPTED; 2497 break; 2498 case 'D': 2499 case 'd': 2500 switch (cmd[1]) { 2501 case 'E': 2502 case 'e': 2503 result = "deny"; 2504 *keep = NEG_MYMASK; 2505 *add = 0; 2506 break; 2507 case 'I': 2508 case 'i': 2509 result = "disable"; 2510 *keep = NEG_HISMASK; 2511 *add = 0; 2512 break; 2513 default: 2514 return NULL; 2515 } 2516 break; 2517 case 'E': 2518 case 'e': 2519 result = "enable"; 2520 *keep = NEG_HISMASK; 2521 *add = NEG_ENABLED; 2522 break; 2523 default: 2524 return NULL; 2525 } 2526 2527 return result; 2528} 2529 2530static int 2531OptSet(struct cmdargs const *arg) 2532{ 2533 int bit = (int)(long)arg->cmd->args; 2534 const char *cmd; 2535 unsigned keep; /* Keep these bits */ 2536 unsigned add; /* Add these bits */ 2537 2538 if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 2539 return 1; 2540 2541 if (add) 2542 arg->bundle->cfg.opt |= bit; 2543 else 2544 arg->bundle->cfg.opt &= ~bit; 2545 return 0; 2546} 2547 2548static int 2549IfaceAliasOptSet(struct cmdargs const *arg) 2550{ 2551 unsigned save = arg->bundle->cfg.opt; 2552 int result = OptSet(arg); 2553 2554 if (result == 0) 2555 if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 2556 arg->bundle->cfg.opt = save; 2557 log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 2558 result = 2; 2559 } 2560 2561 return result; 2562} 2563 2564static int 2565NegotiateSet(struct cmdargs const *arg) 2566{ 2567 long param = (long)arg->cmd->args; 2568 struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 2569 struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 2570 const char *cmd; 2571 unsigned keep; /* Keep these bits */ 2572 unsigned add; /* Add these bits */ 2573 2574 if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 2575 return 1; 2576 2577 if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 2578 log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 2579 cmd, arg->cmd->name); 2580 return 2; 2581 } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 2582 log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 2583 cmd, arg->cmd->name, cx->name); 2584 cx = NULL; 2585 } 2586 2587 switch (param) { 2588 case NEG_ACFCOMP: 2589 cx->physical->link.lcp.cfg.acfcomp &= keep; 2590 cx->physical->link.lcp.cfg.acfcomp |= add; 2591 break; 2592 case NEG_CHAP05: 2593 cx->physical->link.lcp.cfg.chap05 &= keep; 2594 cx->physical->link.lcp.cfg.chap05 |= add; 2595 break; 2596#ifdef HAVE_DES 2597 case NEG_CHAP80: 2598 cx->physical->link.lcp.cfg.chap80nt &= keep; 2599 cx->physical->link.lcp.cfg.chap80nt |= add; 2600 break; 2601 case NEG_CHAP80LM: 2602 cx->physical->link.lcp.cfg.chap80lm &= keep; 2603 cx->physical->link.lcp.cfg.chap80lm |= add; 2604 break; 2605 case NEG_CHAP81: 2606 cx->physical->link.lcp.cfg.chap81 &= keep; 2607 cx->physical->link.lcp.cfg.chap81 |= add; 2608 break; 2609 case NEG_MPPE: 2610 l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 2611 l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 2612 break; 2613#endif 2614 case NEG_DEFLATE: 2615 l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 2616 l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 2617 break; 2618 case NEG_DNS: 2619 arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 2620 arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 2621 break; 2622 case NEG_ENDDISC: 2623 arg->bundle->ncp.mp.cfg.negenddisc &= keep; 2624 arg->bundle->ncp.mp.cfg.negenddisc |= add; 2625 break; 2626 case NEG_LQR: 2627 cx->physical->link.lcp.cfg.lqr &= keep; 2628 cx->physical->link.lcp.cfg.lqr |= add; 2629 break; 2630 case NEG_PAP: 2631 cx->physical->link.lcp.cfg.pap &= keep; 2632 cx->physical->link.lcp.cfg.pap |= add; 2633 break; 2634 case NEG_PPPDDEFLATE: 2635 l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 2636 l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 2637 break; 2638 case NEG_PRED1: 2639 l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 2640 l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 2641 break; 2642 case NEG_PROTOCOMP: 2643 cx->physical->link.lcp.cfg.protocomp &= keep; 2644 cx->physical->link.lcp.cfg.protocomp |= add; 2645 break; 2646 case NEG_SHORTSEQ: 2647 switch (bundle_Phase(arg->bundle)) { 2648 case PHASE_DEAD: 2649 break; 2650 case PHASE_ESTABLISH: 2651 /* Make sure none of our links are DATALINK_LCP or greater */ 2652 if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 2653 log_Printf(LogWARN, "shortseq: Only changable before" 2654 " LCP negotiations\n"); 2655 return 1; 2656 } 2657 break; 2658 default: 2659 log_Printf(LogWARN, "shortseq: Only changable at phase" 2660 " DEAD/ESTABLISH\n"); 2661 return 1; 2662 } 2663 arg->bundle->ncp.mp.cfg.shortseq &= keep; 2664 arg->bundle->ncp.mp.cfg.shortseq |= add; 2665 break; 2666 case NEG_VJCOMP: 2667 arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 2668 arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 2669 break; 2670 } 2671 2672 return 0; 2673} 2674 2675static struct cmdtab const NegotiateCommands[] = { 2676 {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 2677 "filter on PPPoUDP payloads", "disable|enable", 2678 (const void *)OPT_FILTERDECAP}, 2679 {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 2680 "disable|enable", (const void *)OPT_IDCHECK}, 2681 {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 2682 "retain interface addresses", "disable|enable", 2683 (const void *)OPT_IFACEALIAS}, 2684 {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 2685 "disable|enable", (const void *)OPT_KEEPSESSION}, 2686 {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 2687 "disable|enable", (const void *)OPT_LOOPBACK}, 2688 {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 2689 "disable|enable", (const void *)OPT_PASSWDAUTH}, 2690 {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 2691 "disable|enable", (const void *)OPT_PROXY}, 2692 {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 2693 "disable|enable", (const void *)OPT_PROXYALL}, 2694 {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 2695 "disable|enable", (const void *)OPT_SROUTES}, 2696 {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 2697 "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 2698 {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 2699 "disable|enable", (const void *)OPT_THROUGHPUT}, 2700 {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 2701 "disable|enable", (const void *)OPT_UTMP}, 2702 2703#define OPT_MAX 11 /* accept/deny allowed below and not above */ 2704 2705 {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2706 "Address & Control field compression", "accept|deny|disable|enable", 2707 (const void *)NEG_ACFCOMP}, 2708 {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2709 "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 2710 (const void *)NEG_CHAP05}, 2711#ifdef HAVE_DES 2712 {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2713 "Microsoft (NT) CHAP", "accept|deny|disable|enable", 2714 (const void *)NEG_CHAP80}, 2715 {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2716 "Microsoft (NT) CHAP", "accept|deny|disable|enable", 2717 (const void *)NEG_CHAP80LM}, 2718 {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2719 "Microsoft CHAP v2", "accept|deny|disable|enable", 2720 (const void *)NEG_CHAP81}, 2721 {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2722 "MPPE encryption", "accept|deny|disable|enable", 2723 (const void *)NEG_MPPE}, 2724#endif 2725 {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2726 "Deflate compression", "accept|deny|disable|enable", 2727 (const void *)NEG_DEFLATE}, 2728 {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2729 "Deflate (type 24) compression", "accept|deny|disable|enable", 2730 (const void *)NEG_PPPDDEFLATE}, 2731 {"dns", NULL, NegotiateSet, LOCAL_AUTH, 2732 "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 2733 {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 2734 "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 2735 {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2736 "Link Quality Reports", "accept|deny|disable|enable", 2737 (const void *)NEG_LQR}, 2738 {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2739 "Password Authentication protocol", "accept|deny|disable|enable", 2740 (const void *)NEG_PAP}, 2741 {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 2742 "Predictor 1 compression", "accept|deny|disable|enable", 2743 (const void *)NEG_PRED1}, 2744 {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 2745 "Protocol field compression", "accept|deny|disable|enable", 2746 (const void *)NEG_PROTOCOMP}, 2747 {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 2748 "MP Short Sequence Numbers", "accept|deny|disable|enable", 2749 (const void *)NEG_SHORTSEQ}, 2750 {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 2751 "Van Jacobson header compression", "accept|deny|disable|enable", 2752 (const void *)NEG_VJCOMP}, 2753 {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 2754 "Display this message", "accept|deny|disable|enable help|? [value]", 2755 NegotiateCommands}, 2756 {NULL, NULL, NULL}, 2757}; 2758 2759static int 2760NegotiateCommand(struct cmdargs const *arg) 2761{ 2762 if (arg->argc > arg->argn) { 2763 char const *argv[3]; 2764 unsigned keep, add; 2765 int n; 2766 2767 if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 2768 return -1; 2769 argv[2] = NULL; 2770 2771 for (n = arg->argn; n < arg->argc; n++) { 2772 argv[1] = arg->argv[n]; 2773 FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 2774 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 2775 } 2776 } else if (arg->prompt) 2777 prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 2778 arg->argv[arg->argn-1]); 2779 else 2780 log_Printf(LogWARN, "%s command must have arguments\n", 2781 arg->argv[arg->argn] ); 2782 2783 return 0; 2784} 2785 2786const char * 2787command_ShowNegval(unsigned val) 2788{ 2789 switch (val&3) { 2790 case 1: return "disabled & accepted"; 2791 case 2: return "enabled & denied"; 2792 case 3: return "enabled & accepted"; 2793 } 2794 return "disabled & denied"; 2795} 2796 2797static int 2798ClearCommand(struct cmdargs const *arg) 2799{ 2800 struct pppThroughput *t; 2801 struct datalink *cx; 2802 int i, clear_type; 2803 2804 if (arg->argc < arg->argn + 1) 2805 return -1; 2806 2807 if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 2808 cx = arg->cx; 2809 if (!cx) 2810 cx = bundle2datalink(arg->bundle, NULL); 2811 if (!cx) { 2812 log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 2813 return 1; 2814 } 2815 t = &cx->physical->link.stats.total; 2816 } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 2817 t = &arg->bundle->ncp.ipcp.throughput; 2818 else 2819 return -1; 2820 2821 if (arg->argc > arg->argn + 1) { 2822 clear_type = 0; 2823 for (i = arg->argn + 1; i < arg->argc; i++) 2824 if (strcasecmp(arg->argv[i], "overall") == 0) 2825 clear_type |= THROUGHPUT_OVERALL; 2826 else if (strcasecmp(arg->argv[i], "current") == 0) 2827 clear_type |= THROUGHPUT_CURRENT; 2828 else if (strcasecmp(arg->argv[i], "peak") == 0) 2829 clear_type |= THROUGHPUT_PEAK; 2830 else 2831 return -1; 2832 } else 2833 clear_type = THROUGHPUT_ALL; 2834 2835 throughput_clear(t, clear_type, arg->prompt); 2836 return 0; 2837} 2838 2839static int 2840RunListCommand(struct cmdargs const *arg) 2841{ 2842 const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 2843 2844#ifndef NONAT 2845 if (arg->cmd->args == NatCommands && 2846 tolower(*arg->argv[arg->argn - 1]) == 'a') { 2847 if (arg->prompt) 2848 prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 2849 else 2850 log_Printf(LogWARN, "The alias command is deprecated\n"); 2851 } 2852#endif 2853 2854 if (arg->argc > arg->argn) 2855 FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 2856 arg->prompt, arg->cx); 2857 else if (arg->prompt) 2858 prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 2859 " <option>' for syntax help.\n", cmd, cmd); 2860 else 2861 log_Printf(LogWARN, "%s command must have arguments\n", cmd); 2862 2863 return 0; 2864} 2865 2866static int 2867IfaceAddCommand(struct cmdargs const *arg) 2868{ 2869 int bits, n, how; 2870 struct in_addr ifa, mask, brd; 2871 2872 if (arg->argc == arg->argn + 1) { 2873 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 2874 return -1; 2875 mask.s_addr = brd.s_addr = INADDR_BROADCAST; 2876 } else { 2877 if (arg->argc == arg->argn + 2) { 2878 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 2879 return -1; 2880 n = 1; 2881 } else if (arg->argc == arg->argn + 3) { 2882 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 2883 return -1; 2884 if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 2885 return -1; 2886 n = 2; 2887 } else 2888 return -1; 2889 2890 if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 2891 return -1; 2892 } 2893 2894 how = IFACE_ADD_LAST; 2895 if (arg->cmd->args) 2896 how |= IFACE_FORCE_ADD; 2897 2898 return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 2899} 2900 2901static int 2902IfaceDeleteCommand(struct cmdargs const *arg) 2903{ 2904 struct in_addr ifa; 2905 int ok; 2906 2907 if (arg->argc != arg->argn + 1) 2908 return -1; 2909 2910 if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 2911 return -1; 2912 2913 if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 2914 arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 2915 log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 2916 inet_ntoa(ifa)); 2917 return 1; 2918 } 2919 2920 ok = iface_inDelete(arg->bundle->iface, ifa); 2921 if (!ok) { 2922 if (arg->cmd->args) 2923 ok = 1; 2924 else if (arg->prompt) 2925 prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 2926 else 2927 log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 2928 } 2929 2930 return !ok; 2931} 2932 2933static int 2934IfaceClearCommand(struct cmdargs const *arg) 2935{ 2936 int how; 2937 2938 if (arg->argc != arg->argn) 2939 return -1; 2940 2941 how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 2942 arg->bundle->phys_type.all & PHYS_AUTO ? 2943 IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 2944 iface_Clear(arg->bundle->iface, how); 2945 2946 return 0; 2947} 2948 2949static int 2950SetProcTitle(struct cmdargs const *arg) 2951{ 2952 static char title[LINE_LEN]; 2953 char *argv[MAXARGS], *ptr; 2954 int len, remaining, f, argc = arg->argc - arg->argn; 2955 2956 if (arg->argc == arg->argn) { 2957 SetTitle(NULL); 2958 return 0; 2959 } 2960 2961 if (argc >= sizeof argv / sizeof argv[0]) { 2962 argc = sizeof argv / sizeof argv[0] - 1; 2963 log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 2964 } 2965 command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 2966 2967 ptr = title; 2968 remaining = sizeof title - 1; 2969 for (f = 0; f < argc && remaining; f++) { 2970 if (f) { 2971 *ptr++ = ' '; 2972 remaining--; 2973 } 2974 len = strlen(argv[f]); 2975 if (len > remaining) 2976 len = remaining; 2977 memcpy(ptr, argv[f], len); 2978 remaining -= len; 2979 ptr += len; 2980 } 2981 *ptr = '\0'; 2982 2983 SetTitle(title); 2984 2985 return 0; 2986}
|