diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index 5a695660601f..032fd2ab3093 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -1,1162 +1,1190 @@ /* * PPP User command processing module * * Written by Toshiharu OHNO (tony-o@iij.ad.jp) * * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the Internet Initiative Japan, Inc. The name of the * IIJ may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.c,v 1.37 1997/04/09 17:35:52 ache Exp $ + * $Id: command.c,v 1.38 1997/04/14 23:48:12 brian Exp $ * */ #include #include #include #include #include #include "fsm.h" #include "phase.h" #include "lcp.h" #include "ipcp.h" #include "modem.h" #include "filter.h" #include "command.h" #include "hdlc.h" #include "vars.h" #include "auth.h" #include #include #include #include #include "os.h" #include extern int MakeArgs(); extern void Cleanup(), TtyTermMode(), PacketMode(); extern int EnableCommand(), DisableCommand(), DisplayCommand(); extern int AcceptCommand(), DenyCommand(); extern int LocalAuthCommand(); extern int LoadCommand(), SaveCommand(); extern int ChangeParity(char *); extern int SelectSystem(); extern int ShowRoute(); extern void TtyOldMode(), TtyCommandMode(); extern struct pppvars pppVars; extern struct cmdtab const SetCommands[]; extern char *IfDevName; struct in_addr ifnetmask; int randinit; static int ShowCommand(), TerminalCommand(), QuitCommand(); static int CloseCommand(), DialCommand(), DownCommand(); static int SetCommand(), AddCommand(), DeleteCommand(); static int ShellCommand(); static int HelpCommand(list, argc, argv, plist) struct cmdtab *list; int argc; char **argv; struct cmdtab *plist; { struct cmdtab *cmd; int n; char c; if (argc > 0) { for (cmd = plist; cmd->name; cmd++) { if (strcmp(cmd->name, *argv) == 0 && (cmd->lauth & VarLocalAuth)) { if (plist == SetCommands) printf("set "); printf("%s %s\n", cmd->name, cmd->syntax); return(1); } } return(1); } n = 0; for (cmd = plist; cmd->func; cmd++) { if (cmd->name && (cmd->lauth & VarLocalAuth)) { c = (n & 1)? '\n' : '\t'; printf(" %-8s: %-20s%c", cmd->name, cmd->helpmes, c); n++; } } if (n & 1) printf("\n"); return(1); } int IsInteractive() { char *mes = NULL; if (mode & MODE_DDIAL) mes = "Working in dedicated dial mode."; else if (mode & MODE_AUTO) mes = "Working in auto mode."; else if (mode & MODE_DIRECT) mes = "Working in direct mode."; else if (mode & MODE_DEDICATED) mes = "Working in dedicated mode."; if (mes) { printf("%s\n", mes); return(0); } return(1); } static int DialCommand(cmdlist, argc, argv) struct cmdtab *cmdlist; int argc; char **argv; { int tries; if (LcpFsm.state > ST_CLOSED) { printf("LCP state is [%s]\n", StateNames[LcpFsm.state]); return(1); } if (!IsInteractive()) return(1); if (argc > 0) { if (SelectSystem(*argv, CONFFILE) < 0) { printf("%s: not found.\n", *argv); return(1); } } tries = 0; do { printf("Dial attempt %u\n", ++tries); modem = OpenModem(mode); if (modem < 0) { printf("failed to open modem.\n"); break; } if (DialModem()) { sleep(1); ModemTimeout(); PacketMode(); break; } } while (VarDialTries == 0 || tries < VarDialTries); return(1); } static int ShellCommand(cmdlist, argc, argv) struct cmdtab *cmdlist; int argc; char **argv; { const char *shell; pid_t shpid; if((shell = getenv("SHELL")) == 0) { shell = _PATH_BSHELL; } #ifdef SHELL_ONLY_INTERACTIVELY #ifndef HAVE_SHELL_CMD_WITH_ANY_MODE if( mode != MODE_INTER) { fprintf(stdout, "Can only start a shell in interactive mode\n"); return(1); } #else if(argc == 0 && !(mode & MODE_INTER)) { fprintf(stderr, "Can only start an interactive shell in interactive mode\n"); return(1); } #endif /* HAVE_SHELL_CMD_WITH_ANY_MODE */ #else if ((mode & (MODE_AUTO|MODE_INTER)) == (MODE_AUTO|MODE_INTER)) { fprintf(stdout, "Shell is not allowed interactively in auto mode\n"); return(1); } #endif /* SHELL_ONLY_INTERACTIVELY */ if((shpid = fork()) == 0) { int dtablesize, i ; for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++) (void)close(i); /* * We are running setuid, we should change to * real user for avoiding security problems. */ if (setgid(getgid()) < 0) { perror("setgid"); exit(1); } if (setuid(getuid()) < 0) { perror("setuid"); exit(1); } TtyOldMode(); if(argc > 0) { /* substitute pseudo args */ for (i=1; i 0? argv[0]: shell); exit(255); } if( shpid == (pid_t)-1 ) { fprintf(stdout, "Fork failed\n"); } else { int status; (void)waitpid(shpid, &status, 0); } TtyCommandMode(1); return(0); } static char StrOption[] = "option .."; static char StrRemote[] = "[remote]"; char StrNull[] = ""; struct cmdtab const Commands[] = { { "accept", NULL, AcceptCommand, LOCAL_AUTH, "accept option request", StrOption}, { "add", NULL, AddCommand, LOCAL_AUTH, "add route", "dest mask gateway"}, { "close", NULL, CloseCommand, LOCAL_AUTH, "Close connection", StrNull}, { "delete", NULL, DeleteCommand, LOCAL_AUTH, "delete route", "ALL | dest gateway [mask]"}, { "deny", NULL, DenyCommand, LOCAL_AUTH, "Deny option request", StrOption}, { "dial", "call", DialCommand, LOCAL_AUTH, "Dial and login", StrRemote}, { "disable", NULL, DisableCommand, LOCAL_AUTH, "Disable option", StrOption}, { "display", NULL, DisplayCommand, LOCAL_AUTH, "Display option configs", StrNull}, { "enable", NULL, EnableCommand, LOCAL_AUTH, "Enable option", StrOption}, { "passwd", NULL, LocalAuthCommand,LOCAL_NO_AUTH, "Password for manipulation", StrOption}, { "load", NULL, LoadCommand, LOCAL_AUTH, "Load settings", StrRemote}, { "save", NULL, SaveCommand, LOCAL_AUTH, "Save settings", StrNull}, { "set", "setup", SetCommand, LOCAL_AUTH, "Set parameters", "var value"}, { "shell", "!", ShellCommand, LOCAL_AUTH, "Run a subshell", "[sh command]"}, { "show", NULL, ShowCommand, LOCAL_AUTH, "Show status and statictics", "var"}, { "term", NULL, TerminalCommand,LOCAL_AUTH, "Enter to terminal mode", StrNull}, { "quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, "Quit PPP program", "[all]"}, { "help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, "Display this message", "[command]", (void *)Commands }, { NULL, "down", DownCommand, LOCAL_AUTH, "Generate down event", StrNull}, { NULL, NULL, NULL }, }; extern int ReportCcpStatus(); extern int ReportLcpStatus(); extern int ReportIpcpStatus(); extern int ReportProtStatus(); extern int ReportCompress(); extern int ShowModemStatus(); extern int ReportHdlcStatus(); extern int ShowMemMap(); static char *LogLevelName[] = { LM_PHASE, LM_CHAT, LM_LQM, LM_LCP, LM_TCPIP, LM_HDLC, LM_ASYNC, LM_LINK, LM_CONNECT, LM_CARRIER, }; static int ShowDebugLevel() { int i; printf("%02x: ", loglevel); for (i = LOG_PHASE; i < MAXLOGLEVEL; i++) { if (loglevel & (1 << i)) printf("%s ", LogLevelName[i]); } printf("\n"); return(1); } static int ShowEscape() { int code, bit; if (EscMap[32]) { for (code = 0; code < 32; code++) { if (EscMap[code]) { for (bit = 0; bit < 8; bit++) { if (EscMap[code] & (1<= 0) { printf(" %d seconds, ", VarRedialTimeout); } else { printf(" Random 0 - %d seconds, ", REDIAL_PERIOD); } printf(" Redial Next Timer: "); if (VarRedialNextTimeout >= 0) { printf(" %d seconds, ", VarRedialNextTimeout); } else { printf(" Random 0 - %d seconds, ", REDIAL_PERIOD); } if (VarDialTries) printf("%d dial tries", VarDialTries); printf("\n"); return(1); } #ifdef MSEXT static int ShowMSExt() { printf(" MS PPP extention values \n" ); printf(" Primary NS : %s\n", inet_ntoa( ns_entries[0] )); printf(" Secondary NS : %s\n", inet_ntoa( ns_entries[1] )); printf(" Primary NBNS : %s\n", inet_ntoa( nbns_entries[0] )); printf(" Secondary NBNS : %s\n", inet_ntoa( nbns_entries[1] )); return(1); } #endif /* MSEXT */ extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter(); struct cmdtab const ShowCommands[] = { { "afilter", NULL, ShowAfilter, LOCAL_AUTH, "Show keep Alive filters", StrOption}, { "auth", NULL, ShowAuthKey, LOCAL_AUTH, "Show auth name/key", StrNull}, { "ccp", NULL, ReportCcpStatus, LOCAL_AUTH, "Show CCP status", StrNull}, { "compress", NULL, ReportCompress, LOCAL_AUTH, "Show compression statictics", StrNull}, { "debug", NULL, ShowDebugLevel, LOCAL_AUTH, "Show current debug level", StrNull}, { "dfilter", NULL, ShowDfilter, LOCAL_AUTH, "Show Demand filters", StrOption}, { "escape", NULL, ShowEscape, LOCAL_AUTH, "Show escape characters", StrNull}, { "hdlc", NULL, ReportHdlcStatus, LOCAL_AUTH, "Show HDLC error summary", StrNull}, { "ifilter", NULL, ShowIfilter, LOCAL_AUTH, "Show Input filters", StrOption}, { "ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH, "Show IPCP status", StrNull}, { "lcp", NULL, ReportLcpStatus, LOCAL_AUTH, "Show LCP status", StrNull}, { "log", NULL, ShowLogList, LOCAL_AUTH, "Show log records", StrNull}, { "mem", NULL, ShowMemMap, LOCAL_AUTH, "Show memory map", StrNull}, { "modem", NULL, ShowModemStatus, LOCAL_AUTH, "Show modem setups", StrNull}, { "ofilter", NULL, ShowOfilter, LOCAL_AUTH, "Show Output filters", StrOption}, { "proto", NULL, ReportProtStatus, LOCAL_AUTH, "Show protocol summary", StrNull}, + { "reconnect",NULL, ShowReconnect, LOCAL_AUTH, + "Show Reconnect timer ntries", StrNull}, + { "redial", NULL, ShowRedial, LOCAL_AUTH, + "Show Redial timeout value", StrNull}, { "route", NULL, ShowRoute, LOCAL_AUTH, "Show routing table", StrNull}, { "timeout", NULL, ShowTimeout, LOCAL_AUTH, "Show Idle timeout value", StrNull}, - { "redial", NULL, ShowRedial, LOCAL_AUTH, - "Show Redial timeout value", StrNull}, #ifdef MSEXT { "msext", NULL, ShowMSExt, LOCAL_AUTH, "Show MS PPP extentions", StrNull}, #endif /* MSEXT */ { "version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, "Show version string", StrNull}, { "help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, "Display this message", StrNull, (void *)ShowCommands}, { NULL, NULL, NULL }, }; struct cmdtab * FindCommand(cmds, str, pmatch) struct cmdtab *cmds; char *str; int *pmatch; { int nmatch = 0; int len = strlen(str); struct cmdtab *found = NULL; while (cmds->func) { if (cmds->name && strncmp(str, cmds->name, len) == 0) { nmatch++; found = cmds; } else if (cmds->alias && strncmp(str, cmds->alias, len) == 0) { nmatch++; found = cmds; } cmds++; } *pmatch = nmatch; return(found); } int FindExec(cmdlist, argc, argv) struct cmdtab *cmdlist; int argc; char **argv; { struct cmdtab *cmd; int val = 1; int nmatch; cmd = FindCommand(cmdlist, *argv, &nmatch); if (nmatch > 1) printf("Ambiguous.\n"); else if (cmd && ( cmd->lauth & VarLocalAuth ) ) val = (cmd->func)(cmd, --argc, ++argv, cmd->args); else printf("what?\n"); return(val); } int aft_cmd = 1; void Prompt() { char *pconnect, *pauth; if (!(mode & MODE_INTER)) return; if (!aft_cmd) printf("\n"); else aft_cmd = 0; if ( VarLocalAuth == LOCAL_AUTH ) pauth = " ON "; else pauth = " on "; if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK) pconnect = "PPP"; else pconnect = "ppp"; printf("%s%s%s> ", pconnect, pauth, VarShortHost); fflush(stdout); } void DecodeCommand(buff, nb, prompt) char *buff; int nb; int prompt; { char *vector[20]; char **argv; int argc, val; char *cp; val = 1; if (nb > 0) { cp = buff + strcspn(buff, "\r\n"); if (cp) *cp = '\0'; { argc = MakeArgs(buff, &vector); argv = vector; if (argc > 0) val = FindExec(Commands, argc, argv); } } if (val && prompt) Prompt(0); } static int ShowCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int val = 1; if (argc > 0) val = FindExec(ShowCommands, argc, argv); else printf("Use ``show ?'' to get a list.\n"); return(val); } static int TerminalCommand() { if (LcpFsm.state > ST_CLOSED) { printf("LCP state is [%s]\n", StateNames[LcpFsm.state]); return(1); } if (!IsInteractive()) return(1); modem = OpenModem(mode); if (modem < 0) { printf("failed to open modem.\n"); return(1); } printf("Enter to terminal mode.\n"); printf("Type `~?' for help.\n"); TtyTermMode(); return(0); } static int QuitCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { if (mode & (MODE_DIRECT|MODE_DEDICATED|MODE_AUTO)) { if (argc > 0 && (VarLocalAuth & LOCAL_AUTH)) { Cleanup(EX_NORMAL); mode &= ~MODE_INTER; } else { LogPrintf(LOG_PHASE_BIT, "client connection closed.\n"); VarLocalAuth = LOCAL_NO_AUTH; close(netfd); close(1); dup2(2, 1); /* Have to have something here or the modem will be 1 */ netfd = -1; mode &= ~MODE_INTER; } } else Cleanup(EX_NORMAL); return(1); } static int CloseCommand() { LcpClose(); return(1); } static int DownCommand() { LcpDown(); return(1); } -static int SetModemSpeed(list, argc, argv) +static int +SetModemSpeed(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int speed; if (argc > 0) { if (strcmp(*argv, "sync") == 0) { VarSpeed = 0; return(1); } speed = atoi(*argv); if (IntToSpeed(speed) != B0) { VarSpeed = speed; return(1); } printf("invalid speed.\n"); } return(1); } -static int SetRedialTimeout(list, argc, argv) +static int +SetReconnect(list, argc, argv) +struct cmdtab *list; +int argc; +char **argv; +{ + if (argc == 2) { + VarReconnectTimer = atoi(argv[0]); + VarReconnectTries = atoi(argv[1]); + } else + printf("Usage: %s %s\n", list->name, list->syntax); + return(1); +} + +static int +SetRedialTimeout(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int timeout; int tries; char *dot; if (argc == 1 || argc == 2 ) { if (strncasecmp(argv[0], "random", 6) == 0 && (argv[0][6] == '\0' || argv[0][6] == '.')) { VarRedialTimeout = -1; printf("Using random redial timeout.\n"); if (!randinit) { randinit = 1; if (srandomdev() < 0) srandom((unsigned long)(time(NULL) ^ getpid())); } } else { timeout = atoi(argv[0]); if (timeout >= 0) { VarRedialTimeout = timeout; } else { printf("invalid redial timeout\n"); printf("Usage: %s %s\n", list->name, list->syntax); } } dot = index(argv[0],'.'); if (dot) { if (strcasecmp(++dot, "random") == 0) { VarRedialNextTimeout = -1; printf("Using random next redial timeout.\n"); if (!randinit) { randinit = 1; if (srandomdev() < 0) srandom((unsigned long)(time(NULL) ^ getpid())); } } else { timeout = atoi(dot); if (timeout >= 0) { VarRedialNextTimeout = timeout; } else { printf("invalid next redial timeout\n"); printf("Usage: %s %s\n", list->name, list->syntax); } } } else VarRedialNextTimeout = NEXT_REDIAL_PERIOD; /* Default next timeout */ if (argc == 2) { tries = atoi(argv[1]); if (tries >= 0) { VarDialTries = tries; } else { printf("invalid retry value\n"); printf("Usage: %s %s\n", list->name, list->syntax); } } } else { printf("Usage: %s %s\n", list->name, list->syntax); } return(1); } -static int SetModemParity(list, argc, argv) +static int +SetModemParity(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int parity; if (argc > 0) { parity = ChangeParity(*argv); if (parity < 0) printf("Invalid parity.\n"); else VarParity = parity; } return(1); } static int SetDebugLevel(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int level, w; for (level = 0; argc-- > 0; argv++) { if (isdigit(**argv)) { w = atoi(*argv); if (w < 0 || w >= MAXLOGLEVEL) { printf("invalid log level.\n"); break; } else level |= (1 << w); } else { for (w = 0; w < MAXLOGLEVEL; w++) { if (strcasecmp(*argv, LogLevelName[w]) == 0) { level |= (1 << w); continue; } } } } loglevel = level; return(1); } static int SetEscape(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int code; for (code = 0; code < 33; code++) EscMap[code] = 0; while (argc-- > 0) { sscanf(*argv++, "%x", &code); code &= 0xff; EscMap[code >> 3] |= (1 << (code&7)); EscMap[32] = 1; } return(1); } static int SetInitialMRU(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int mru; if (argc > 0) { mru = atoi(*argv); if (mru < 100) printf("given value is too small.\n"); else if (mru > MAX_MRU) printf("given value is too big.\n"); else VarMRU = mru; } return(1); } static int SetIdleTimeout(list, argc, argv) struct cmdtab *list; int argc; char **argv; { if (argc-- > 0) { VarIdleTimeout = atoi(*argv++); if (argc-- > 0) { VarLqrTimeout = atoi(*argv++); if (VarLqrTimeout < 1) VarLqrTimeout = 30; if (argc > 0) { VarRetryTimeout = atoi(*argv); if (VarRetryTimeout < 1 || VarRetryTimeout > 10) VarRetryTimeout = 3; } } } return(1); } struct in_addr GetIpAddr(cp) char *cp; { struct hostent *hp; struct in_addr ipaddr; hp = gethostbyname(cp); if (hp && hp->h_addrtype == AF_INET) bcopy(hp->h_addr, &ipaddr, hp->h_length); else if (inet_aton(cp, &ipaddr) == 0) ipaddr.s_addr = 0; return(ipaddr); } static int SetInterfaceAddr(list, argc, argv) struct cmdtab *list; int argc; char **argv; { DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L; if (argc > 0) { ParseAddr(argc, argv++, &DefMyAddress.ipaddr, &DefMyAddress.mask, &DefMyAddress.width); if (--argc > 0) { ParseAddr(argc, argv++, &DefHisAddress.ipaddr, &DefHisAddress.mask, &DefHisAddress.width); if (--argc > 0) { ifnetmask = GetIpAddr(*argv); if (--argc > 0) { ParseAddr(argc, argv++, &DefTriggerAddress.ipaddr, &DefTriggerAddress.mask, &DefTriggerAddress.width); } } } } /* * For backwards compatibility, 0.0.0.0 means any address. */ if (DefMyAddress.ipaddr.s_addr == 0) { DefMyAddress.mask.s_addr = 0; DefMyAddress.width = 0; } if (DefHisAddress.ipaddr.s_addr == 0) { DefHisAddress.mask.s_addr = 0; DefHisAddress.width = 0; } if ((mode & MODE_AUTO) || ((mode & MODE_DEDICATED) && dstsystem)) { OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask); } return(1); } #ifdef MSEXT void SetMSEXT(pri_addr, sec_addr, argc, argv) struct in_addr *pri_addr; struct in_addr *sec_addr; int argc; char **argv; { int dummyint; struct in_addr dummyaddr; pri_addr->s_addr = sec_addr->s_addr = 0L; if( argc > 0 ) { ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint); if( --argc > 0 ) ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint); else sec_addr->s_addr = pri_addr->s_addr; } /* * if the primary/secondary ns entries are 0.0.0.0 we should * set them to either the localhost's ip, or the values in * /etc/resolv.conf ?? * * up to you if you want to implement this... */ } static int SetNS(list, argc, argv) struct cmdtab *list; int argc; char **argv; { SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv); return(1); } static int SetNBNS(list, argc, argv) struct cmdtab *list; int argc; char **argv; { SetMSEXT(&nbns_entries[0], &nbns_entries[1], argc, argv); return(1); } #endif /* MS_EXT */ #define VAR_AUTHKEY 0 #define VAR_DIAL 1 #define VAR_LOGIN 2 #define VAR_AUTHNAME 3 #define VAR_DEVICE 4 #define VAR_ACCMAP 5 #define VAR_PHONE 6 static int SetVariable(list, argc, argv, param) struct cmdtab *list; int argc; char **argv; int param; { u_long map; if (argc > 0) { switch (param) { case VAR_AUTHKEY: strncpy(VarAuthKey, *argv, sizeof(VarAuthKey)-1); VarAuthKey[sizeof(VarAuthKey)-1] = '\0'; break; case VAR_AUTHNAME: strncpy(VarAuthName, *argv, sizeof(VarAuthName)-1); VarAuthName[sizeof(VarAuthName)-1] = '\0'; break; case VAR_DIAL: strncpy(VarDialScript, *argv, sizeof(VarDialScript)-1); VarDialScript[sizeof(VarDialScript)-1] = '\0'; break; case VAR_LOGIN: strncpy(VarLoginScript, *argv, sizeof(VarLoginScript)-1); VarLoginScript[sizeof(VarLoginScript)-1] = '\0'; break; case VAR_DEVICE: strncpy(VarDevice, *argv, sizeof(VarDevice)-1); VarDevice[sizeof(VarDevice)-1] = '\0'; break; case VAR_ACCMAP: sscanf(*argv, "%lx", &map); VarAccmap = map; break; case VAR_PHONE: strncpy(VarPhoneList, *argv, sizeof(VarPhoneList)-1); VarPhoneList[sizeof(VarPhoneList)-1] = '\0'; strcpy(VarPhoneCopy, VarPhoneList); VarNextPhone = VarPhoneCopy; break; } } return(1); } static int SetCtsRts(list, argc, argv) struct cmdtab *list; int argc; char **argv; { if (argc > 0) { if (strcmp(*argv, "on") == 0) VarCtsRts = TRUE; else if (strcmp(*argv, "off") == 0) VarCtsRts = FALSE; else printf("usage: set ctsrts [on|off].\n"); } return(1); } static int SetOpenMode(list, argc, argv) struct cmdtab *list; int argc; char **argv; { if (argc > 0) { if (strcmp(*argv, "active") == 0) VarOpenMode = OPEN_ACTIVE; else if (strcmp(*argv, "passive") == 0) VarOpenMode = OPEN_PASSIVE; else printf("Invalid mode.\n"); } return(1); } static char StrChatStr[] = "chat-script"; static char StrValue[] = "value"; extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter(); struct cmdtab const SetCommands[] = { { "accmap", NULL, SetVariable, LOCAL_AUTH, "Set accmap value", "hex-value", (void *)VAR_ACCMAP}, { "afilter", NULL, SetAfilter, LOCAL_AUTH, "Set keep Alive filter", "..."}, { "authkey", "key", SetVariable, LOCAL_AUTH, "Set authentication key", "key", (void *)VAR_AUTHKEY}, { "authname", NULL, SetVariable, LOCAL_AUTH, "Set authentication name", "name", (void *)VAR_AUTHNAME}, { "ctsrts", NULL, SetCtsRts, LOCAL_AUTH, "Use CTS/RTS modem signalling", "[on|off]"}, { "debug", NULL, SetDebugLevel, LOCAL_AUTH, "Set debug level", StrValue}, { "device", "line", SetVariable, LOCAL_AUTH, "Set modem device name", "device-name", (void *)VAR_DEVICE}, { "dfilter", NULL, SetDfilter, LOCAL_AUTH, "Set demand filter", "..."}, { "dial", NULL, SetVariable, LOCAL_AUTH, "Set dialing script", StrChatStr, (void *)VAR_DIAL}, { "escape", NULL, SetEscape, LOCAL_AUTH, "Set escape characters", "hex-digit ..."}, { "ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "Set destination address", "[src-addr [dst-addr [netmask [trg-addr]]]]"}, { "ifilter", NULL, SetIfilter, LOCAL_AUTH, "Set input filter", "..."}, { "login", NULL, SetVariable, LOCAL_AUTH, "Set login script", StrChatStr, (void *)VAR_LOGIN }, { "mru", "mtu", SetInitialMRU, LOCAL_AUTH, "Set Initial MRU value", StrValue }, { "ofilter", NULL, SetOfilter, LOCAL_AUTH, "Set output filter", "..." }, { "openmode", NULL, SetOpenMode, LOCAL_AUTH, "Set open mode", "[active|passive]"}, { "parity", NULL, SetModemParity, LOCAL_AUTH, "Set modem parity", "[odd|even|none]"}, { "phone", NULL, SetVariable, LOCAL_AUTH, "Set telephone number(s)", "phone1[:phone2[...]]", (void *)VAR_PHONE }, + { "reconnect",NULL, SetReconnect, LOCAL_AUTH, + "Set Reconnect timeout", "value ntries"}, + { "redial", NULL, SetRedialTimeout, LOCAL_AUTH, + "Set Redial timeout", "value|random[.value|random] [dial_attempts]"}, { "speed", NULL, SetModemSpeed, LOCAL_AUTH, "Set modem speed", "speed"}, { "timeout", NULL, SetIdleTimeout, LOCAL_AUTH, "Set Idle timeout", StrValue}, - { "redial", NULL, SetRedialTimeout, LOCAL_AUTH, - "Set Redial timeout", "value|random[.value|random] [dial_attempts]"}, #ifdef MSEXT { "ns", NULL, SetNS, LOCAL_AUTH, "Set NameServer", "pri-addr [sec-addr]"}, { "nbns", NULL, SetNBNS, LOCAL_AUTH, "Set NetBIOS NameServer", "pri-addr [sec-addr]"}, #endif /* MSEXT */ { "help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, "Display this message", StrNull, (void *)SetCommands}, { NULL, NULL, NULL }, }; static int SetCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { int val = 1; if (argc > 0) val = FindExec(SetCommands, argc, argv); else printf("Use `set ?' to get a list or `set ? ' for syntax help.\n"); return(val); } static int AddCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { struct in_addr dest, gateway, netmask; if (argc == 3) { dest = GetIpAddr(argv[0]); netmask = GetIpAddr(argv[1]); if (strcmp(argv[2], "HISADDR") == 0) gateway = IpcpInfo.his_ipaddr; else gateway = GetIpAddr(argv[2]); OsSetRoute(RTM_ADD, dest, gateway, netmask); } else { printf("Usage: %s %s\n", list->name, list->syntax); } return(1); } static int DeleteCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { struct in_addr dest, gateway, netmask; if (argc >= 2) { dest = GetIpAddr(argv[0]); if (strcmp(argv[1], "HISADDR") == 0) gateway = IpcpInfo.his_ipaddr; else gateway = GetIpAddr(argv[1]); netmask.s_addr = 0; if (argc == 3) { if (inet_aton(argv[1], &netmask) == 0) { printf("bad netmask value.\n"); return(1); } } OsSetRoute(RTM_DELETE, dest, gateway, netmask); } else if (argc == 1 && strcmp(argv[0], "ALL") == 0) { DeleteIfRoutes(0); } else { printf("Usage: %s %s\n", list->name, list->syntax); } return(1); } diff --git a/usr.sbin/ppp/defs.h b/usr.sbin/ppp/defs.h index 5a9533f8be88..edcc665c2622 100644 --- a/usr.sbin/ppp/defs.h +++ b/usr.sbin/ppp/defs.h @@ -1,98 +1,100 @@ /* * Written by Toshiharu OHNO (tony-o@iij.ad.jp) * * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the Internet Initiative Japan. The name of the * IIJ may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: defs.h,v 1.10 1997/02/22 16:10:10 peter Exp $ + * $Id: defs.h,v 1.11 1997/04/14 23:48:13 brian Exp $ * * TODO: */ #ifndef _DEFS_H_ #define _DEFS_H_ #include #include #include #include #include #include #include #include "mbuf.h" #include "log.h" /* * Check follwiing definitions for your machine envirinment */ #define LOGFILE "/var/log/ppp.log" /* Name of log file */ #ifdef __FreeBSD__ #define MODEM_DEV "/dev/cuaa1" /* name of tty device */ #else #define MODEM_DEV "/dev/tty01" /* name of tty device */ #endif #define MODEM_SPEED B38400 /* tty speed */ #define SERVER_PORT 3000 /* Base server port no. */ #define MODEM_CTSRTS TRUE /* Default (true): use CTS/RTS signals */ +#define RECONNECT_TIMER 3 /* Default timer for carrier loss */ +#define RECONNECT_TRIES 0 /* Default retries on carrier loss */ #define REDIAL_PERIOD 30 /* Default Hold time to redial */ #define NEXT_REDIAL_PERIOD 3 /* Default Hold time to next number redial */ #define CONFFILE "ppp.conf" #define LINKFILE "ppp.linkup" #define ETHERFILE "ppp.etherup" #define SECRETFILE "ppp.secret" /* * Definition of working mode */ #define MODE_INTER 1 /* Interactive mode */ #define MODE_AUTO 2 /* Auto calling mode */ #define MODE_DIRECT 4 /* Direct connection mode */ #define MODE_DEDICATED 8 /* Dedicated line mode */ #define MODE_DDIAL 16 /* Dedicated dialing line mode */ #define MODE_ALIAS 32 /* Packet aliasing (masquerading) */ #define MODE_BACKGROUND 64 /* Background mode. */ #define EX_NORMAL 0 #define EX_START 1 #define EX_SOCK 2 #define EX_MODEM 3 #define EX_DIAL 4 #define EX_DEAD 5 #define EX_DONE 6 #define EX_REBOOT 7 #define EX_ERRDEAD 8 #define EX_HANGUP 10 #define EX_TERM 11 #define EX_NODIAL 12 #define EX_NOLOGIN 13 int mode; int BGFiledes[2]; int modem; int tun_in, tun_out; int netfd; char *dstsystem; #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif #endif /* _DEFS_H_ */ diff --git a/usr.sbin/ppp/ip.c b/usr.sbin/ppp/ip.c index 1e6647341193..8d13cc570a98 100644 --- a/usr.sbin/ppp/ip.c +++ b/usr.sbin/ppp/ip.c @@ -1,409 +1,410 @@ /* * PPP IP Protocol Interface * * Written by Toshiharu OHNO (tony-o@iij.ad.jp) * * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the Internet Initiative Japan. The name of the * IIJ may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id$ + * $Id: ip.c,v 1.14 1997/02/22 16:10:18 peter Exp $ * * TODO: * o Return ICMP message for filterd packet * and optionaly record it into log. */ #include "fsm.h" #include "lcpproto.h" #include "hdlc.h" #include #include #include #include #include #include #include "vars.h" #include "filter.h" #include "alias.h" extern void SendPppFrame(); extern void LcpClose(); static struct pppTimer IdleTimer; static void IdleTimeout() { LogPrintf(LOG_PHASE_BIT, "Idle timer expired.\n"); LcpClose(); + lostCarrier = 0; } /* * Start Idle timer. If timeout is reached, we call LcpClose() to * close LCP and link. */ void StartIdleTimer() { if (!(mode & (MODE_DEDICATED|MODE_DDIAL))) { StopTimer(&IdleTimer); IdleTimer.func = IdleTimeout; IdleTimer.load = VarIdleTimeout * SECTICKS; IdleTimer.state = TIMER_STOPPED; StartTimer(&IdleTimer); } } void StopIdleTimer() { StopTimer(&IdleTimer); } /* * If any IP layer traffic is detected, refresh IdleTimer. */ static void RestartIdleTimer() { if (!(mode & (MODE_DEDICATED|MODE_DDIAL)) && ipKeepAlive ) { StartTimer(&IdleTimer); ipIdleSecs = 0; } } static u_short interactive_ports[32] = { 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, }; #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) static char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG", }; static char *Direction[] = { "INP", "OUT", "OUT", "IN/OUT" }; static struct filterent *Filters[] = { ifilters, ofilters, dfilters, afilters }; static int PortMatch(op, pport, rport) int op; u_short pport, rport; { switch (op) { case OP_EQ: return(pport == rport); case OP_GT: return(pport > rport); case OP_LT: return(pport < rport); default: return(0); } } /* * Check a packet against with defined filters */ static int FilterCheck(pip, direction) struct ip *pip; int direction; { struct filterent *fp = Filters[direction]; int gotinfo, cproto, estab, n; struct tcphdr *th; struct udphdr *uh; struct icmp *ih; char *ptop; u_short sport, dport; if (fp->action) { cproto = gotinfo = estab = 0; sport = dport = 0; for (n = 0; n < MAXFILTERS; n++) { if (fp->action) { /* permit fragments on in and out filter */ if ((direction == FL_IN || direction == FL_OUT) && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) { return(A_PERMIT); } #ifdef DEBUG logprintf("rule = %d\n", n); #endif if ((pip->ip_src.s_addr & fp->smask.s_addr) == fp->saddr.s_addr && (pip->ip_dst.s_addr & fp->dmask.s_addr) == fp->daddr.s_addr) { if (fp->proto) { if (!gotinfo) { ptop = (char *)pip + (pip->ip_hl << 2); switch (pip->ip_p) { case IPPROTO_ICMP: cproto = P_ICMP; ih = (struct icmp *)ptop; sport = ih->icmp_type; estab = 1; break; case IPPROTO_UDP: cproto = P_UDP; uh = (struct udphdr *)ptop; sport = ntohs(uh->uh_sport); dport = ntohs(uh->uh_dport); estab = 1; break; case IPPROTO_TCP: cproto = P_TCP; th = (struct tcphdr *)ptop; sport = ntohs(th->th_sport); dport = ntohs(th->th_dport); estab = (th->th_flags & TH_ACK); #ifdef DEBUG if (estab == 0) logprintf("flag = %02x, sport = %d, dport = %d\n", th->th_flags, sport, dport); #endif break; default: return(A_DENY); /* We'll block unknown type of packet */ } gotinfo = 1; #ifdef DEBUG logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d\n", direction, cproto, fp->opt.srcop, fp->opt.dstop, estab); #endif } #ifdef DEBUG logprintf("check0: rule = %d, proto = %d, sport = %d, dport = %d\n", n, cproto, sport, dport); logprintf("check0: action = %d\n", fp->action); #endif if (cproto == fp->proto) { if ((fp->opt.srcop == OP_NONE || PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && (fp->opt.dstop == OP_NONE || PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && (fp->opt.estab == 0 || estab)) { return(fp->action); } } } else { /* Address is mached. Make a decision. */ #ifdef DEBUG logprintf("check1: action = %d\n", fp->action); #endif return(fp->action); } } } fp++; } return(A_DENY); /* No rule is mached. Deny this packet */ } return(A_PERMIT); /* No rule is given. Permit this packet */ } static void IcmpError(pip, code) struct ip *pip; int code; { #ifdef notdef struct mbuf *bp; if (pip->ip_p != IPPROTO_ICMP) { bp = mballoc(cnt, MB_IPIN); bcopy(ptr, MBUF_CTOP(bp), cnt); SendPppFrame(bp); RestartIdleTimer(); ipOutOctets += cnt; } #endif } /* * For debugging aid. */ int PacketCheck(cp, nb, direction) char *cp; int nb; int direction; { struct ip *pip; struct tcphdr *th; struct udphdr *uh; struct icmp *icmph; char *ptop; int mask, len, n; int logit; int pri = PRI_NORMAL; logit = (loglevel & (1 << LOG_TCPIP)); pip = (struct ip *)cp; if (logit) logprintf("%s ", Direction[direction]); ptop = (cp + (pip->ip_hl << 2)); switch (pip->ip_p) { case IPPROTO_ICMP: if (logit) { icmph = (struct icmp *)ptop; logprintf("ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), icmph->icmp_type); } break; case IPPROTO_UDP: if (logit) { uh = (struct udphdr *)ptop; logprintf("UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); } break; case IPPROTO_TCP: th = (struct tcphdr *)ptop; if (pip->ip_tos == IPTOS_LOWDELAY) pri = PRI_FAST; else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) pri = PRI_FAST; } if (logit) { len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); logprintf("TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); logprintf("%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); n = 0; for (mask = TH_FIN; mask != 0x40; mask <<= 1) { if (th->th_flags & mask) logprintf(" %s", TcpFlags[n]); n++; } logprintf(" seq:%x ack:%x (%d/%d)\n", ntohl(th->th_seq), ntohl(th->th_ack), len, nb); if ((th->th_flags & TH_SYN) && nb > 40) { u_short *sp; ptop += 20; sp = (u_short *)ptop; if (ntohs(sp[0]) == 0x0204) logprintf(" MSS = %d\n", ntohs(sp[1])); } } break; } if ((FilterCheck(pip, direction) & A_DENY)) { #ifdef DEBUG logprintf("blocked.\n"); #endif if (direction == 0) IcmpError(pip, pri); return(-1); } else { if ( FilterCheck(pip, FL_KEEP ) & A_DENY ) { /* Check Keep Alive filter */ ipKeepAlive = FALSE; } else { ipKeepAlive = TRUE; } return(pri); } } void IpInput(bp) struct mbuf *bp; /* IN: Pointer to IP pakcet */ { u_char *cp; struct mbuf *wp; int nb, nw; u_char tunbuff[MAX_MRU]; cp = tunbuff; nb = 0; for (wp = bp; wp; wp = wp->next) { /* Copy to continuois region */ bcopy(MBUF_CTOP(wp), cp, wp->cnt); cp += wp->cnt; nb += wp->cnt; } if (mode & MODE_ALIAS) { PacketAliasIn((struct ip *)tunbuff); nb = ntohs(((struct ip *)tunbuff)->ip_len); } if ( PacketCheck(tunbuff, nb, FL_IN ) < 0) { pfree(bp); return; } ipInOctets += nb; /* * Pass it to tunnel device */ nw = write(tun_out, tunbuff, nb); if (nw != nb) fprintf(stderr, "wrote %d, got %d\r\n", nb, nw); pfree(bp); RestartIdleTimer(); } static struct mqueue IpOutputQueues[PRI_FAST+1]; void IpEnqueue(pri, ptr, count) int pri; char *ptr; int count; { struct mbuf *bp; bp = mballoc(count, MB_IPQ); bcopy(ptr, MBUF_CTOP(bp), count); Enqueue(&IpOutputQueues[pri], bp); } int IsIpEnqueued() { struct mqueue *queue; int exist = FALSE; for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) { if ( queue->qlen > 0 ) { exist = TRUE; break; } } return( exist ); } void IpStartOutput() { struct mqueue *queue; struct mbuf *bp; int pri, cnt; if (IpcpFsm.state != ST_OPENED) return; pri = PRI_FAST; for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) { if (queue->top) { bp = Dequeue(queue); if (bp) { cnt = plength(bp); SendPppFrame(bp); RestartIdleTimer(); ipOutOctets += cnt; break; } } pri--; } } diff --git a/usr.sbin/ppp/main.c b/usr.sbin/ppp/main.c index bb876af27993..f1e1d00b0a8b 100644 --- a/usr.sbin/ppp/main.c +++ b/usr.sbin/ppp/main.c @@ -1,1005 +1,1019 @@ /* * User Process PPP * * Written by Toshiharu OHNO (tony-o@iij.ad.jp) * * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the Internet Initiative Japan, Inc. The name of the * IIJ may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: main.c,v 1.43 1997/04/13 00:54:43 brian Exp $ + * $Id: main.c,v 1.44 1997/04/14 23:48:15 brian Exp $ * * TODO: * o Add commands for traffic summary, version display, etc. * o Add signal handler for misc controls. */ #include "fsm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "modem.h" #include "os.h" #include "hdlc.h" #include "ccp.h" #include "lcp.h" #include "ipcp.h" #include "vars.h" #include "auth.h" #include "filter.h" #include "systems.h" #include "ip.h" #include "alias.h" #include "sig.h" #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" #define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n" #ifndef O_NONBLOCK #ifdef O_NDELAY #define O_NONBLOCK O_NDELAY #endif #endif extern void VjInit(), AsyncInit(); extern void AsyncInput(), IpOutput(); extern int SelectSystem(); extern void DecodeCommand(), Prompt(); extern int aft_cmd; extern int IsInteractive(); extern struct in_addr ifnetmask; static void DoLoop(void); static void TerminalStop(); static struct termios oldtio; /* Original tty mode */ static struct termios comtio; /* Command level tty mode */ int TermMode; static int server; static pid_t BGPid = 0; struct sockaddr_in ifsin; char pid_filename[128]; static void TtyInit() { struct termios newtio; int stat; stat = fcntl(0, F_GETFL, 0); stat |= O_NONBLOCK; fcntl(0, F_SETFL, stat); newtio = oldtio; newtio.c_lflag &= ~(ECHO|ISIG|ICANON); newtio.c_iflag = 0; newtio.c_oflag &= ~OPOST; newtio.c_cc[VEOF] = _POSIX_VDISABLE; newtio.c_cc[VINTR] = _POSIX_VDISABLE; newtio.c_cc[VMIN] = 1; newtio.c_cc[VTIME] = 0; newtio.c_cflag |= CS8; tcsetattr(0, TCSADRAIN, &newtio); comtio = newtio; } /* * Set tty into command mode. We allow canonical input and echo processing. */ void TtyCommandMode(prompt) int prompt; { struct termios newtio; int stat; if (!(mode & MODE_INTER)) return; tcgetattr(0, &newtio); newtio.c_lflag |= (ECHO|ISIG|ICANON); newtio.c_iflag = oldtio.c_iflag; newtio.c_oflag |= OPOST; tcsetattr(0, TCSADRAIN, &newtio); stat = fcntl(0, F_GETFL, 0); stat |= O_NONBLOCK; fcntl(0, F_SETFL, stat); TermMode = 0; if(prompt) Prompt(0); } /* * Set tty into terminal mode which is used while we invoke term command. */ void TtyTermMode() { int stat; tcsetattr(0, TCSADRAIN, &comtio); stat = fcntl(0, F_GETFL, 0); stat &= ~O_NONBLOCK; fcntl(0, F_SETFL, stat); TermMode = 1; } void TtyOldMode() { int stat; stat = fcntl(0, F_GETFL, 0); stat &= ~O_NONBLOCK; fcntl(0, F_SETFL, stat); tcsetattr(0, TCSANOW, &oldtio); } void Cleanup(excode) int excode; { OsLinkdown(); OsCloseLink(1); sleep(1); if (mode & (MODE_AUTO | MODE_BACKGROUND)) { DeleteIfRoutes(1); unlink(pid_filename); } OsInterfaceDown(1); if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { char c = EX_ERRDEAD; if (write(BGFiledes[1],&c,1) == 1) LogPrintf(LOG_PHASE_BIT,"Parent notified of failure.\n"); else LogPrintf(LOG_PHASE_BIT,"Failed to notify parent of failure.\n"); close(BGFiledes[1]); } LogPrintf(LOG_PHASE_BIT, "PPP Terminated %d.\n",excode); LogClose(); if (server >= 0) { close(server); server = -1; } TtyOldMode(); exit(excode); } static void Hangup(signo) int signo; { if (signo == SIGSEGV) { LogPrintf(LOG_PHASE_BIT, "Signal %d, core dump.\n", signo); LogClose(); abort(); } if (BGPid) { kill (BGPid, SIGTERM); exit (EX_HANGUP); } else { LogPrintf(LOG_PHASE_BIT, "Signal %d, hangup.\n", signo); Cleanup(EX_HANGUP); } } static void CloseSession(signo) int signo; { if (BGPid) { kill (BGPid, SIGINT); exit (EX_TERM); } else { LogPrintf(LOG_PHASE_BIT, "Signal %d, terminate.\n", signo); LcpClose(); Cleanup(EX_TERM); } } static void TerminalCont() { pending_signal(SIGCONT, SIG_DFL); pending_signal(SIGTSTP, TerminalStop); TtyCommandMode(getpgrp() == tcgetpgrp(0)); } static void TerminalStop(signo) int signo; { pending_signal(SIGCONT, TerminalCont); TtyOldMode(); pending_signal(SIGTSTP, SIG_DFL); kill(getpid(), signo); } void Usage() { fprintf(stderr, "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); exit(EX_START); } void ProcessArgs(int argc, char **argv) { int optc; char *cp; optc = 0; while (argc > 0 && **argv == '-') { cp = *argv + 1; if (strcmp(cp, "auto") == 0) mode |= MODE_AUTO; else if (strcmp(cp, "background") == 0) mode |= MODE_BACKGROUND; else if (strcmp(cp, "direct") == 0) mode |= MODE_DIRECT; else if (strcmp(cp, "dedicated") == 0) mode |= MODE_DEDICATED; else if (strcmp(cp, "ddial") == 0) mode |= MODE_DDIAL|MODE_AUTO; else if (strcmp(cp, "alias") == 0) { mode |= MODE_ALIAS; optc--; /* this option isn't exclusive */ } else Usage(); optc++; argv++; argc--; } if (argc > 1) { fprintf(stderr, "specify only one system label.\n"); exit(EX_START); } if (argc == 1) dstsystem = *argv; if (optc > 1) { fprintf(stderr, "specify only one mode.\n"); exit(EX_START); } } static void Greetings() { printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); fflush(stdout); } void main(argc, argv) int argc; char **argv; { int tunno; argc--; argv++; mode = MODE_INTER; /* default operation is interactive mode */ netfd = server = modem = tun_in = -1; ProcessArgs(argc, argv); Greetings(); GetUid(); IpcpDefAddress(); InitAlias(); if (SelectSystem("default", CONFFILE) < 0) { fprintf(stderr, "Warning: No default entry is given in config file.\n"); } if (LogOpen()) exit(EX_START); switch ( LocalAuthInit() ) { case NOT_FOUND: fprintf(stderr,LAUTH_M1); fprintf(stderr,LAUTH_M2); fflush (stderr); /* Fall down */ case VALID: VarLocalAuth = LOCAL_AUTH; break; default: break; } if (OpenTunnel(&tunno) < 0) { perror("open_tun"); exit(EX_START); } if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED|MODE_BACKGROUND)) mode &= ~MODE_INTER; if (mode & MODE_INTER) { printf("Interactive mode\n"); netfd = STDIN_FILENO; } else if (mode & MODE_AUTO) { printf("Automatic Dialer mode\n"); if (dstsystem == NULL) { fprintf(stderr, "Destination system must be specified in auto or ddial mode.\n"); exit(EX_START); } } else if (mode & MODE_BACKGROUND) { printf("Background mode\n"); if (dstsystem == NULL) { fprintf(stderr, "Destination system must be specified in background mode.\n"); exit(EX_START); } } tcgetattr(0, &oldtio); /* Save original tty mode */ pending_signal(SIGHUP, LogReOpen); pending_signal(SIGTERM, CloseSession); pending_signal(SIGINT, CloseSession); pending_signal(SIGQUIT, CloseSession); #ifdef SIGSEGV signal(SIGSEGV, Hangup); #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif #ifdef SIGALRM pending_signal(SIGALRM, SIG_IGN); #endif if(mode & MODE_INTER) { #ifdef SIGTSTP pending_signal(SIGTSTP, TerminalStop); #endif #ifdef SIGTTIN pending_signal(SIGTTIN, TerminalStop); #endif #ifdef SIGTTOU pending_signal(SIGTTOU, SIG_IGN); #endif } if (dstsystem) { if (SelectSystem(dstsystem, CONFFILE) < 0) { fprintf(stderr, "Destination system not found in conf file.\n"); Cleanup(EX_START); } if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { fprintf(stderr, "Must specify dstaddr with auto or ddial mode.\n"); Cleanup(EX_START); } } if (mode & MODE_DIRECT) printf("Packet mode enabled.\n"); #ifdef notdef if (mode & MODE_AUTO) { OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); } #endif if (!(mode & MODE_INTER)) { int port = SERVER_PORT + tunno; if (mode & MODE_BACKGROUND) { if (pipe (BGFiledes)) { perror("pipe"); Cleanup(EX_SOCK); } } else { /* * Create server socket and listen at there. */ server = socket(PF_INET, SOCK_STREAM, 0); if (server < 0) { perror("socket"); Cleanup(EX_SOCK); } ifsin.sin_family = AF_INET; ifsin.sin_addr.s_addr = INADDR_ANY; ifsin.sin_port = htons(port); if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { perror("bind"); if (errno == EADDRINUSE) fprintf(stderr, "Wait for a while, then try again.\n"); Cleanup(EX_SOCK); } listen(server, 5); } DupLog(); if (!(mode & MODE_DIRECT)) { int fd; char pid[32]; pid_t bgpid; bgpid = fork (); if (bgpid == -1) { perror ("fork"); Cleanup (EX_SOCK); } if (bgpid) { char c = EX_NORMAL; if (mode & MODE_BACKGROUND) { /* Wait for our child to close its pipe before we exit. */ BGPid = bgpid; close (BGFiledes[1]); if (read(BGFiledes[0], &c, 1) != 1) LogPrintf (LOG_PHASE_BIT, "Parent: Child exit, no status.\n"); else if (c == EX_NORMAL) LogPrintf (LOG_PHASE_BIT, "Parent: PPP enabled.\n"); else LogPrintf (LOG_PHASE_BIT, "Parent: Child failed %d.\n",(int)c); close (BGFiledes[0]); } exit(c); } else if (mode & MODE_BACKGROUND) close(BGFiledes[0]); snprintf(pid_filename, sizeof (pid_filename), "%s/ppp.tun%d.pid", _PATH_VARRUN, tunno); unlink(pid_filename); snprintf(pid, sizeof(pid), "%d\n", (int)getpid()); if ((fd = open(pid_filename, O_RDWR|O_CREAT, 0666)) != -1) { write(fd, pid, strlen(pid)); close(fd); } } if (server >= 0) LogPrintf(LOG_PHASE_BIT, "Listening at %d.\n", port); #ifdef DOTTYINIT if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ #else if (mode & MODE_DIRECT) { #endif TtyInit(); } else { int fd; setsid(); /* detach control tty */ if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDERR_FILENO); if (fd > 2) (void)close (fd); } } } else { TtyInit(); TtyCommandMode(1); } LogPrintf(LOG_PHASE_BIT, "PPP Started.\n"); do DoLoop(); while (mode & MODE_DEDICATED); Cleanup(EX_DONE); } /* * Turn into packet mode, where we speak PPP. */ void PacketMode() { if (RawModem(modem) < 0) { fprintf(stderr, "Not connected.\r\n"); return; } AsyncInit(); VjInit(); LcpInit(); IpcpInit(); CcpInit(); LcpUp(); if (mode & (MODE_DIRECT|MODE_DEDICATED)) LcpOpen(OPEN_ACTIVE); else LcpOpen(VarOpenMode); if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { TtyCommandMode(1); fprintf(stderr, "Packet mode.\r\n"); aft_cmd = 1; } } static void ShowHelp() { fprintf(stderr, "The following commands are available:\r\n"); fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); fprintf(stderr, " ~-\tDecrease log level\r\n"); fprintf(stderr, " ~+\tIncrease log level\r\n"); fprintf(stderr, " ~.\tTerminate program\r\n"); fprintf(stderr, " ~?\tThis help\r\n"); } static void ReadTty() { int n; char ch; static int ttystate; #define MAXLINESIZE 200 char linebuff[MAXLINESIZE]; #ifdef DEBUG logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); #endif if (!TermMode) { n = read(netfd, linebuff, sizeof(linebuff)-1); aft_cmd = 1; if (n > 0) { DecodeCommand(linebuff, n, 1); } else { LogPrintf(LOG_PHASE_BIT, "client connection closed.\n"); VarLocalAuth = LOCAL_NO_AUTH; close(netfd); close(1); dup2(2, 1); /* Have to have something here or the modem will be 1 */ netfd = -1; mode &= ~MODE_INTER; } return; } /* * We are in terminal mode, decode special sequences */ n = read(0, &ch, 1); #ifdef DEBUG logprintf("got %d bytes\n", n); #endif if (n > 0) { switch (ttystate) { case 0: if (ch == '~') ttystate++; else write(modem, &ch, n); break; case 1: switch (ch) { case '?': ShowHelp(); break; case '-': if (loglevel > 0) { loglevel--; fprintf(stderr, "New loglevel is %d\r\n", loglevel); } break; case '+': loglevel++; fprintf(stderr, "New loglevel is %d\r\n", loglevel); break; #ifdef DEBUG case 'm': ShowMemMap(); break; #endif case 'p': /* * XXX: Should check carrier. */ if (LcpFsm.state <= ST_CLOSED) { VarOpenMode = OPEN_ACTIVE; PacketMode(); } break; #ifdef DEBUG case 't': ShowTimers(); break; #endif case '.': TermMode = 1; TtyCommandMode(1); break; default: if (write(modem, &ch, n) < 0) fprintf(stderr, "err in write.\r\n"); break; } ttystate = 0; break; } } } /* * Here, we'll try to detect HDLC frame */ static char *FrameHeaders[] = { "\176\377\003\300\041", "\176\377\175\043\300\041", "\176\177\175\043\100\041", "\176\175\337\175\043\300\041", "\176\175\137\175\043\100\041", NULL, }; u_char * HdlcDetect(cp, n) u_char *cp; int n; { char *ptr, *fp, **hp; cp[n] = '\0'; /* be sure to null terminated */ ptr = NULL; for (hp = FrameHeaders; *hp; hp++) { fp = *hp; if (DEV_IS_SYNC) fp++; ptr = strstr((char *)cp, fp); if (ptr) break; } return((u_char *)ptr); } static struct pppTimer RedialTimer; static void RedialTimeout() { StopTimer(&RedialTimer); LogPrintf(LOG_PHASE_BIT, "Redialing timer expired.\n"); } static void StartRedialTimer(Timeout) int Timeout; { StopTimer(&RedialTimer); if (Timeout) { RedialTimer.state = TIMER_STOPPED; if (Timeout > 0) RedialTimer.load = Timeout * SECTICKS; else RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; LogPrintf(LOG_PHASE_BIT, "Enter pause (%d) for redialing.\n", RedialTimer.load / SECTICKS); RedialTimer.func = RedialTimeout; StartTimer(&RedialTimer); } } static void DoLoop() { fd_set rfds, wfds, efds; int pri, i, n, wfd, nfds; struct sockaddr_in hisaddr; struct timeval timeout, *tp; int ssize = sizeof(hisaddr); u_char *cp; u_char rbuff[MAX_MRU]; int dial_up; int tries; int qlen; pid_t pgroup; pgroup = getpgrp(); if (mode & (MODE_DIRECT|MODE_BACKGROUND)) { modem = OpenModem(mode); LogPrintf(LOG_PHASE_BIT, "Packet mode enabled\n"); fflush(stderr); PacketMode(); } else if (mode & MODE_DEDICATED) { if (modem < 0) modem = OpenModem(mode); } fflush(stdout); timeout.tv_sec = 0; timeout.tv_usec = 0; + lostCarrier = 0; if (mode & MODE_BACKGROUND) dial_up = TRUE; /* Bring the line up */ else dial_up = FALSE; /* XXXX */ tries = 0; for (;;) { nfds = 0; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); /* * If the link is down and we're in DDIAL mode, bring it back * up. */ if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) dial_up = TRUE; + /* + * If we lost carrier and want to re-establish the connection + * due to the "set reconnect" value, we'd better bring the line + * back up now. + */ + if (LcpFsm.state <= ST_CLOSED && dial_up != TRUE + && lostCarrier && lostCarrier <= VarReconnectTries) { + LogPrintf(LOG_PHASE_BIT, "Connection lost, re-establish (%d/%d)\n", + lostCarrier, VarReconnectTries); + StartRedialTimer(VarReconnectTimer); + dial_up = TRUE; + } + /* - * If Ip packet for output is enqueued and require dial up, + * If Ip packet for output is enqueued and require dial up, * Just do it! */ - if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */ + if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { #ifdef DEBUG logprintf("going to dial: modem = %d\n", modem); #endif modem = OpenModem(mode); if (modem < 0) { StartRedialTimer(VarRedialTimeout); } else { tries++; /* Tries are per number, not per list of numbers. */ if (VarDialTries) LogPrintf(LOG_CHAT_BIT, "Dial attempt %u of %d\n", tries, VarDialTries); else LogPrintf(LOG_CHAT_BIT, "Dial attempt %u\n", tries); if (DialModem()) { sleep(1); /* little pause to allow peer starts */ ModemTimeout(); PacketMode(); dial_up = FALSE; tries = 0; } else { CloseModem(); if (mode & MODE_BACKGROUND) { if (VarNextPhone == NULL) Cleanup(EX_DIAL); /* Tried all numbers - no luck */ else /* Try all numbers in background mode */ StartRedialTimer(VarRedialNextTimeout); } else if (VarDialTries && tries >= VarDialTries) { /* I give up ! Can't get through :( */ StartRedialTimer(VarRedialTimeout); dial_up = FALSE; tries = 0; } else if (VarNextPhone == NULL) /* Dial failed. Keep quite during redial wait period. */ StartRedialTimer(VarRedialTimeout); else StartRedialTimer(VarRedialNextTimeout); } } } qlen = ModemQlen(); if (qlen == 0) { IpStartOutput(); qlen = ModemQlen(); } if (modem >= 0) { if (modem + 1 > nfds) nfds = modem + 1; FD_SET(modem, &rfds); FD_SET(modem, &efds); if (qlen > 0) { FD_SET(modem, &wfds); } } if (server >= 0) { if (server + 1 > nfds) nfds = server + 1; FD_SET(server, &rfds); } /* *** IMPORTANT *** * * CPU is serviced every TICKUNIT micro seconds. * This value must be chosen with great care. If this values is * too big, it results loss of characters from modem and poor responce. * If this values is too small, ppp process eats many CPU time. */ #ifndef SIGALRM usleep(TICKUNIT); TimerService(); #else handle_signals(); #endif /* If there are aren't many packets queued, look for some more. */ if (qlen < 20 && tun_in >= 0) { if (tun_in + 1 > nfds) nfds = tun_in + 1; FD_SET(tun_in, &rfds); } if (netfd >= 0) { if (netfd + 1 > nfds) nfds = netfd + 1; FD_SET(netfd, &rfds); FD_SET(netfd, &efds); } #ifndef SIGALRM /* * Normally, select() will not block because modem is writable. * In AUTO mode, select will block until we find packet from tun */ tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; i = select(nfds, &rfds, &wfds, &efds, tp); #else /* * When SIGALRM timer is running, a select function will be * return -1 and EINTR after a Time Service signal hundler * is done. If the redial timer is not running and we are * trying to dial, poll with a 0 value timer. */ tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; i = select(nfds, &rfds, &wfds, &efds, tp); #endif if ( i == 0 ) { continue; } if ( i < 0 ) { if ( errno == EINTR ) { handle_signals(); continue; } perror("select"); break; } if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { logprintf("Exception detected.\n"); break; } if (server >= 0 && FD_ISSET(server, &rfds)) { LogPrintf(LOG_PHASE_BIT, "connected to client.\n"); wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); if (wfd < 0) { perror("accept"); continue; } if (netfd >= 0) { write(wfd, "already in use.\n", 16); close(wfd); continue; } else netfd = wfd; if (dup2(netfd, 1) < 0) { perror("dup2"); close(netfd); netfd = -1; continue; } mode |= MODE_INTER; Greetings(); switch ( LocalAuthInit() ) { case NOT_FOUND: fprintf(stdout,LAUTH_M1); fprintf(stdout,LAUTH_M2); fflush(stdout); /* Fall down */ case VALID: VarLocalAuth = LOCAL_AUTH; break; default: break; } (void) IsInteractive(); Prompt(0); } if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { /* something to read from tty */ ReadTty(); } if (modem >= 0) { if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ ModemStartOutput(modem); } if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ if (LcpFsm.state <= ST_CLOSED) usleep(10000); n = read(modem, rbuff, sizeof(rbuff)); if ((mode & MODE_DIRECT) && n <= 0) { DownConnection(); } else LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); if (LcpFsm.state <= ST_CLOSED) { /* * In dedicated mode, we just discard input until LCP is started. */ if (!(mode & MODE_DEDICATED)) { cp = HdlcDetect(rbuff, n); if (cp) { /* * LCP packet is detected. Turn ourselves into packet mode. */ if (cp != rbuff) { write(1, rbuff, cp - rbuff); write(1, "\r\n", 2); } PacketMode(); #ifdef notdef AsyncInput(cp, n - (cp - rbuff)); #endif } else write(1, rbuff, n); } } else { if (n > 0) AsyncInput(rbuff, n); #ifdef notdef continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ #endif } } } if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ n = read(tun_in, rbuff, sizeof(rbuff)); if (n < 0) { perror("read from tun"); continue; } /* * Process on-demand dialup. Output packets are queued within tunnel * device until IPCP is opened. */ if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { pri = PacketCheck(rbuff, n, FL_DIAL); if (pri >= 0) { if (mode & MODE_ALIAS) { PacketAliasOut((struct ip *)rbuff); n = ntohs(((struct ip *)rbuff)->ip_len); } IpEnqueue(pri, rbuff, n); dial_up = TRUE; /* XXX */ } continue; } pri = PacketCheck(rbuff, n, FL_OUT); if (pri >= 0) { if (mode & MODE_ALIAS) { PacketAliasOut((struct ip *)rbuff); n = ntohs(((struct ip *)rbuff)->ip_len); } IpEnqueue(pri, rbuff, n); } } } logprintf("job done.\n"); } diff --git a/usr.sbin/ppp/modem.c b/usr.sbin/ppp/modem.c index ead30acd6150..fb0bb3c66250 100644 --- a/usr.sbin/ppp/modem.c +++ b/usr.sbin/ppp/modem.c @@ -1,813 +1,814 @@ /* * PPP Modem handling module * * Written by Toshiharu OHNO (tony-o@iij.ad.jp) * * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the Internet Initiative Japan, Inc. The name of the * IIJ may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: modem.c,v 1.32 1997/03/31 22:51:00 brian Exp $ + * $Id: modem.c,v 1.33 1997/04/13 00:54:44 brian Exp $ * * TODO: */ #include "fsm.h" #include #include #include #include #include #include #include #include "hdlc.h" #include "lcp.h" #include "ip.h" #include "modem.h" #include "vars.h" #ifndef O_NONBLOCK #ifdef O_NDELAY #define O_NONBLOCK O_NDELAY #endif #endif extern int DoChat(); static int mbits; /* Current DCD status */ static int connect_time; /* connection time */ static int connect_count; static struct pppTimer ModemTimer; static char uucplock[10]; extern void PacketMode(), TtyTermMode(), TtyCommandMode(); extern int TermMode; #define Online (mbits & TIOCM_CD) static struct mbuf *modemout; static struct mqueue OutputQueues[PRI_LINK+1]; static int dev_is_modem; #undef QDEBUG void Enqueue(queue, bp) struct mqueue *queue; struct mbuf *bp; { if (queue->last) { queue->last->pnext = bp; queue->last = bp; } else queue->last = queue->top = bp; queue->qlen++; #ifdef QDEBUG logprintf("Enqueue: len = %d\n", queue->qlen); #endif } struct mbuf * Dequeue(queue) struct mqueue *queue; { struct mbuf *bp; #ifdef QDEBUG logprintf("Dequeue: len = %d\n", queue->qlen); #endif bp = queue->top; if (bp) { queue->top = queue->top->pnext; queue->qlen--; if (queue->top == NULL) { queue->last = queue->top; #ifdef QDEBUG if (queue->qlen) logprintf("!!! not zero (%d)!!!\n", queue->qlen); #endif } } return(bp); } static struct speeds{ int nspeed; speed_t speed; } speeds[] = { #ifdef B50 { 50, B50, }, #endif #ifdef B75 { 75, B75, }, #endif #ifdef B110 { 110, B110, }, #endif #ifdef B134 { 134, B134, }, #endif #ifdef B150 { 150, B150, }, #endif #ifdef B200 { 200, B200, }, #endif #ifdef B300 { 300, B300, }, #endif #ifdef B600 { 600, B600, }, #endif #ifdef B1200 { 1200, B1200, }, #endif #ifdef B1800 { 1800, B1800, }, #endif #ifdef B2400 { 2400, B2400, }, #endif #ifdef B4800 { 4800, B4800, }, #endif #ifdef B9600 { 9600, B9600, }, #endif #ifdef B19200 { 19200, B19200, }, #endif #ifdef B38400 { 38400, B38400, }, #endif #ifndef _POSIX_SOURCE #ifdef B7200 { 7200, B7200, }, #endif #ifdef B14400 { 14400, B14400, }, #endif #ifdef B28800 { 28800, B28800, }, #endif #ifdef B57600 { 57600, B57600, }, #endif #ifdef B76800 { 76800, B76800, }, #endif #ifdef B115200 { 115200, B115200, }, #endif #ifdef B230400 { 230400, B230400, }, #endif #ifdef EXTA { 19200, EXTA, }, #endif #ifdef EXTB { 38400, EXTB, }, #endif #endif /*_POSIX_SOURCE */ { 0, 0 } }; int SpeedToInt(speed) speed_t speed; { struct speeds *sp; for (sp = speeds; sp->nspeed; sp++) { if (sp->speed == speed) { return(sp->nspeed); } } return 0; } speed_t IntToSpeed(nspeed) int nspeed; { struct speeds *sp; for (sp = speeds; sp->nspeed; sp++) { if (sp->nspeed == nspeed) { return(sp->speed); } } return B0; } static time_t uptime; void DownConnection() { LogPrintf(LOG_PHASE_BIT, "Disconnected!\n"); LogPrintf(LOG_PHASE_BIT, "Connect time: %d secs\n", time(NULL) - uptime); if (!TermMode) { CloseModem(); LcpDown(); } + lostCarrier++; connect_time = 0; } /* * ModemTimeout() watches DCD signal and notifies if it's status is changed. * */ void ModemTimeout() { int ombits = mbits; int change; StopTimer(&ModemTimer); if (Online) connect_time++; StartTimer(&ModemTimer); if (dev_is_modem) { ioctl(modem, TIOCMGET, &mbits); change = ombits ^ mbits; if (change & TIOCM_CD) { if (Online) { time(&uptime); LogPrintf(LOG_PHASE_BIT, "*Connected!\n"); connect_count++; /* * In dedicated mode, start packet mode immediate * after we detected carrier. */ if (mode & MODE_DEDICATED) PacketMode(); } else { DownConnection(); } } } else { if (!Online) { time(&uptime); LogPrintf(LOG_PHASE_BIT, "Connected!\n"); mbits = TIOCM_CD; connect_count++; connect_time = 0; } else if (uptime == 0) { time(&uptime); } } } void StartModemTimer() { connect_time = 0; StopTimer(&ModemTimer); ModemTimer.state = TIMER_STOPPED; ModemTimer.load = SECTICKS; ModemTimer.func = ModemTimeout; StartTimer(&ModemTimer); } struct parity { char *name; char *name1; int set; } validparity[] = { { "even", "P_EVEN", CS7 | PARENB }, { "odd", "P_ODD", CS7 | PARENB | PARODD }, { "none", "P_ZERO", CS8 }, { NULL, 0 }, }; int GetParityValue(str) char *str; { struct parity *pp; for (pp = validparity; pp->name; pp++) { if (strcasecmp(pp->name, str) == 0 || strcasecmp(pp->name1, str) == 0) { VarParity = pp->set; return(pp->set); } } return(-1); } int ChangeParity(str) char *str; { struct termios rstio; int val; val = GetParityValue(str); if (val > 0) { VarParity = val; tcgetattr(modem, &rstio); rstio.c_cflag &= ~(CSIZE|PARODD|PARENB); rstio.c_cflag |= val; tcsetattr(modem, TCSADRAIN, &rstio); } return(val); } #include #include #include int OpenConnection(host, port) char *host, *port; { struct sockaddr_in dest; int sock; struct hostent *hp; struct servent *sp; dest.sin_family = AF_INET; dest.sin_addr.s_addr = inet_addr(host); if (dest.sin_addr.s_addr == INADDR_NONE) { hp = gethostbyname(host); if (hp) { bcopy(hp->h_addr_list[0], &dest.sin_addr.s_addr, 4); } else { printf("unknown host: %s\n", host); return(-1); } } dest.sin_port = htons(atoi(port)); if (dest.sin_port == 0) { sp = getservbyname(port, "tcp"); if (sp) { dest.sin_port = sp->s_port; } else { printf("unknown service: %s\n", port); return(-1); } } LogPrintf(LOG_PHASE_BIT, "Connected to %s:%s\n", host, port); sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) { return(sock); } if (connect(sock, (struct sockaddr *)&dest, sizeof(dest)) < 0) { printf("connection failed.\n"); return(-1); } return(sock); } static struct termios modemios; int OpenModem(mode) int mode; { struct termios rstio; int oldflag; char *host, *cp, *port; int res; mbits = 0; if (mode & MODE_DIRECT) { if (isatty(0)) { modem = open(ctermid(NULL), O_RDWR|O_NONBLOCK); if (modem < 0) { LogPrintf(LOG_PHASE_BIT, "Open Failed %s\n", ctermid(NULL)); return(modem); } } else if (modem < 0) return(modem); } else if (modem < 0) { if (strncmp(VarDevice, "/dev", 4) == 0) { strncpy(uucplock, rindex(VarDevice, '/')+1,sizeof(uucplock)-1); uucplock[sizeof(uucplock)-1] = '\0'; if ((res = uu_lock(uucplock)) != UU_LOCK_OK) { if (res == UU_LOCK_INUSE) LogPrintf(LOG_PHASE_BIT, "Modem %s is in use\n", VarDevice); else LogPrintf(LOG_PHASE_BIT, "Modem %s is in use: uu_lock: %s\n", VarDevice, uu_lockerr(res)); return(-1); } modem = open(VarDevice, O_RDWR|O_NONBLOCK); if (modem < 0) { LogPrintf(LOG_PHASE_BIT, "Open Failed %s\n", VarDevice); (void) uu_unlock(uucplock); return(modem); } } else { /* XXX: PPP over TCP */ cp = index(VarDevice, ':'); if (cp) { *cp = 0; host = VarDevice; port = cp + 1; if (*host && *port) { modem = OpenConnection(host, port); *cp = ':'; /* Don't destroy VarDevice */ if (modem < 0) return(-1); } else { *cp = ':'; /* Don't destroy VarDevice */ return(-1); } } else return(-1); } } /* This code gets around the problem of closing descriptor 0 * when it should not have been closed and closing descriptor 1 * when the telnet connection dies. Since this program always * opens a descriptor for the modem in auto and direct mode, * having to dup the descriptor here is a fatal error. * * With the other changes I have made this should no longer happen. * JC */ while (modem < 3) { logprintf("Duping modem fd %d\n", modem); modem = dup(modem); } /* * If we are working on tty device, change it's mode into * the one desired for further operation. In this implementation, * we assume that modem is configuted to use CTS/RTS flow control. */ dev_is_modem = isatty(modem) || DEV_IS_SYNC; if (DEV_IS_SYNC) sleep(1); if (dev_is_modem && !DEV_IS_SYNC) { tcgetattr(modem, &rstio); modemios = rstio; #ifdef DEBUG logprintf("## modem = %d\n", modem); logprintf("modem (get): iflag = %x, oflag = %x, cflag = %x\n", rstio.c_iflag, rstio.c_oflag, rstio.c_cflag); #endif cfmakeraw(&rstio); if (VarCtsRts) rstio.c_cflag |= CLOCAL | CCTS_OFLOW|CRTS_IFLOW; else { rstio.c_cflag |= CLOCAL; rstio.c_iflag |= IXOFF; } rstio.c_iflag |= IXON; if (!(mode & MODE_DEDICATED)) rstio.c_cflag |= HUPCL; if ((mode & MODE_DIRECT) == 0) { /* * If we are working as direct mode, don't change tty speed. */ rstio.c_cflag &= ~(CSIZE|PARODD|PARENB); rstio.c_cflag |= VarParity; cfsetspeed(&rstio, IntToSpeed(VarSpeed)); } tcsetattr(modem, TCSADRAIN, &rstio); #ifdef DEBUG logprintf("modem (put): iflag = %x, oflag = %x, cflag = %x\n", rstio.c_iflag, rstio.c_oflag, rstio.c_cflag); #endif if (!(mode & MODE_DIRECT)) ioctl(modem, TIOCMGET, &mbits); #ifdef DEBUG fprintf(stderr, "modem control = %o\n", mbits); #endif oldflag = fcntl(modem, F_GETFL, 0); fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK); } StartModemTimer(); return(modem); } int ModemSpeed() { struct termios rstio; tcgetattr(modem, &rstio); return(SpeedToInt(cfgetispeed(&rstio))); } /* * Put modem tty line into raw mode which is necessary in packet mode operation */ int RawModem(modem) int modem; { struct termios rstio; int oldflag; if (!isatty(modem) || DEV_IS_SYNC) return(0); if (!(mode & MODE_DIRECT) && modem >= 0 && !Online) { #ifdef DEBUG logprintf("mode = %d, modem = %d, mbits = %x\n", mode, modem, mbits); #endif #ifdef notdef return(-1); #endif } tcgetattr(modem, &rstio); cfmakeraw(&rstio); if (VarCtsRts) rstio.c_cflag |= CLOCAL | CCTS_OFLOW|CRTS_IFLOW; else rstio.c_cflag |= CLOCAL; if (!(mode & MODE_DEDICATED)) rstio.c_cflag |= HUPCL; tcsetattr(modem, TCSADRAIN, &rstio); oldflag = fcntl(modem, F_GETFL, 0); fcntl(modem, F_SETFL, oldflag | O_NONBLOCK); #ifdef DEBUG oldflag = fcntl(modem, F_GETFL, 0); logprintf("modem (put2): iflag = %x, oflag = %x, cflag = %x\n", rstio.c_iflag, rstio.c_oflag, rstio.c_cflag); logprintf("flag = %x\n", oldflag); #endif return(0); } void UnrawModem(modem) int modem; { int oldflag; if (isatty(modem) && !DEV_IS_SYNC) { tcsetattr(modem, TCSAFLUSH, &modemios); oldflag = fcntl(modem, F_GETFL, 0); fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK); } } void HangupModem(flag) int flag; { struct termios tio; if (!isatty(modem)) { mbits &= ~TIOCM_DTR; close(modem); modem = -1; /* Mark as modem has closed */ return; } if (modem >= 0 && Online) { mbits &= ~TIOCM_DTR; #ifdef __bsdi__ /* not a POSIX way */ ioctl(modem, TIOCMSET, &mbits); #else tcgetattr(modem, &tio); cfsetspeed(&tio, B0); tcsetattr(modem, TCSANOW, &tio); #endif sleep(1); #ifdef notdef mbits &= ~TIOCM_CD; #endif } /* * If we are working as dedicated mode, never close it * until we are directed to quit program. */ if (modem >= 0 && (flag || !(mode & MODE_DEDICATED))) { ModemTimeout(); /* XXX */ StopTimer(&ModemTimer); /* XXX */ /* ModemTimeout() may call DownConection() to close the modem * resulting in modem == 0. */ if (modem >= 0) { tcflush(modem, TCIOFLUSH); UnrawModem(modem); close(modem); } modem = -1; /* Mark as modem has closed */ (void) uu_unlock(uucplock); } else if (modem >= 0) { mbits |= TIOCM_DTR; #ifndef notyet ioctl(modem, TIOCMSET, &mbits); #else tcgetattr(modem, &ts); cfsetspeed(&ts, IntToSpeed(VarSpeed)); tcsetattr(modem, TCSADRAIN, &ts); #endif } } void CloseModem() { if (modem >= 0) { close(modem); modem = -1; } (void) uu_unlock(uucplock); } /* * Write to modem. Actualy, requested packets are queued, and goes out * to the line when ModemStartOutput() is called. */ void WriteModem(pri, ptr, count) int pri; char *ptr; int count; { struct mbuf *bp; bp = mballoc(count, MB_MODEM); bcopy(ptr, MBUF_CTOP(bp), count); /* Should be NORMAL and LINK only. * All IP frames get here marked NORMAL. */ Enqueue(&OutputQueues[pri], bp); } void ModemOutput(pri, bp) int pri; struct mbuf *bp; { struct mbuf *wp; int len; len = plength(bp); wp = mballoc(len, MB_MODEM); mbread(bp, MBUF_CTOP(wp), len); Enqueue(&OutputQueues[pri], wp); ModemStartOutput(modem); } int ModemQlen() { struct mqueue *queue; int len = 0; int i; for ( i = PRI_NORMAL; i <= PRI_LINK; i ++ ) { queue = &OutputQueues[i]; len += queue->qlen; } return(len); } void ModemStartOutput(fd) int fd; { struct mqueue *queue; int nb, nw, i; if (modemout == NULL && ModemQlen() == 0) IpStartOutput(); if (modemout == NULL) { i = PRI_LINK; for (queue = &OutputQueues[PRI_LINK]; queue >= OutputQueues; queue--) { if (queue->top) { modemout = Dequeue(queue); #ifdef QDEBUG if (i > PRI_NORMAL) { struct mqueue *q; q = &OutputQueues[0]; logprintf("output from queue %d, normal has %d\n", i, q->qlen); } logprintf("Dequeue(%d): ", i); #endif break; } i--; } } if (modemout) { nb = modemout->cnt; if (nb > 1600) nb = 1600; if (fd == 0) fd = 1; /* XXX WTFO! This is bogus */ nw = write(fd, MBUF_CTOP(modemout), nb); #ifdef QDEBUG logprintf("wrote: %d(%d)\n", nw, nb); LogDumpBuff(LOG_HDLC, "modem write", MBUF_CTOP(modemout), nb); #endif if (nw > 0) { modemout->cnt -= nw; modemout->offset += nw; if (modemout->cnt == 0) { modemout = mbfree(modemout); #ifdef QDEBUG logprintf(" mbfree\n"); #endif } } else if (nw < 0) { if (errno != EAGAIN) perror("modem write"); } } } int DialModem() { char ScriptBuffer[200]; int excode = 0; strncpy(ScriptBuffer, VarDialScript,sizeof(ScriptBuffer)-1); ScriptBuffer[sizeof(ScriptBuffer)-1] = '\0'; if (DoChat(ScriptBuffer) > 0) { if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) fprintf(stderr, "dial OK!\n"); strncpy(ScriptBuffer, VarLoginScript,sizeof(ScriptBuffer)-1); if (DoChat(ScriptBuffer) > 0) { if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) fprintf(stderr, "login OK!\n"); return(1); } else { if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { fprintf(stderr, "login failed.\n"); excode = EX_NOLOGIN; } } ModemTimeout(); /* Dummy call to check modem status */ } else { if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { fprintf(stderr, "dial failed.\n"); excode = EX_NODIAL; } } HangupModem(0); return(0); } int ShowModemStatus() { #ifdef TIOCOUTQ int nb; #endif printf("device: %s speed: ", VarDevice); if (DEV_IS_SYNC) printf("sync\n"); else printf("%d\n", VarSpeed); switch (VarParity & CSIZE) { case CS7: printf("cs7, "); break; case CS8: printf("cs8, "); break; } if (VarParity & PARENB) { if (VarParity & PARODD) printf("odd parity, "); else printf("even parity, "); } else printf("no parity, "); printf("CTS/RTS %s.\n", (VarCtsRts? "on" : "off")); #ifdef DEBUG printf("fd = %d, modem control = %o\n", modem, mbits); #endif printf("connect count: %d\n", connect_count); #ifdef TIOCOUTQ ioctl(modem, TIOCOUTQ, &nb); printf("outq: %d\n", nb); #endif printf("outqlen: %d\n", ModemQlen()); printf("DialScript = %s\n", VarDialScript); printf("LoginScript = %s\n", VarLoginScript); printf("PhoneNumber(s) = %s\n", VarPhoneList); return(1); } diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index 26ad29e84eae..f4431ee16183 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -1,1104 +1,1135 @@ .\" manual page [] for ppp 0.94 beta2 + alpha -.\" $Id: ppp.8,v 1.28 1997/04/13 00:54:45 brian Exp $ +.\" $Id: ppp.8,v 1.29 1997/04/14 23:48:17 brian Exp $ .Dd 20 September 1995 .Os FreeBSD .Dt PPP 8 .Sh NAME .Nm ppp .Nd Point to Point Protocol (aka iijppp) .Sh SYNOPSIS .Nm .Op Fl auto | background | ddial | direct | dedicated .Op Fl alias .Op Ar system .Sh DESCRIPTION This is a user process .Em PPP software package. Normally, .Em PPP is implemented as a part of the kernel (e.g. as managed by pppd) and it's thus somewhat hard to debug and/or modify its behavior. However, in this implementation .Em PPP is done as a user process with the help of the tunnel device driver (tun). .Sh Major Features .Bl -diag .It Provides interactive user interface. Using its command mode, the user can easily enter commands to establish the connection with the remote end, check the status of connection and close the connection. All functions can also be optionally password protected for security. .It Supports both manual and automatic dialing. Interactive mode has a .Dq term command which enables you to talk to your modem directly. When your modem is connected to the remote peer and it starts to talk .Em PPP , the .Em PPP software detects it and switches to packet mode automatically. Once you have determined the proper sequence for connecting with the remote host, you can write a chat script to define the necessary dialing and login procedure for later convenience. .It Supports on-demand dialup capability. By using auto mode, .Nm will act as a daemon and wait for a packet to be sent over the .Em PPP link. When this happens, the daemon automatically dials and establishes the connection. In almost the same manner ddial mode (dedicated or demon dialing) also automatically dials and establishes the connection. However, it differs in that it will dial the remote site any time it detects the link is down, even if there are no packets to be sent. This mode is useful for full-time connections who worry less about line charges and more about being connected full time. .It Supports packet aliasing. Packet aliasing, more commonly known as masquerading, allows computers on a private, unregistered network to access the internet. The .Em PPP host acts as a masquerading gateway. IP addresses as well as TCP and UDP port numbers are aliased for outgoing packets and de-aliased for returning packets. .It Supports background PPP connections. In background mode, if .Nm successfully establishes the connection, it will become a daemon. Otherwise, it will exit with an error. .It Supports server-side PPP connections. Can act as server which accepts incoming .Em PPP connections. .It Supports PAP and CHAP authentication. .It Supports Proxy Arp. When .Em PPP is set up as server, you can also configure it to do proxy arp for your connection. .It Supports packet filtering. User can define four kinds of filters: .Em ifilter for incoming packets, .Em ofilter for outgoing packets, .Em dfilter to define a dialing trigger packet and .Em afilter for keeping a connection alive with the trigger packet. .It Tunnel driver supports bpf. The user can use .Xr tcpdump 1 to check the packet flow over the .Em PPP link. .It Supports PPP over TCP capability. .It Supports IETF draft Predictor-1 compression. .Nm supports not only VJ-compression but also Predictor-1 compression. Normally, a modem has built-in compression (e.g. v42.bis) and the system may receive higher data rates from it as a result of such compression. While this is generally a good thing in most other situations, this higher speed data imposes a penalty on the system by increasing the number of serial interrupts the system has to process in talking to the modem and also increases latency. Unlike VJ-compression, Predictor-1 compression pre-compresses .Em all data flowing through the link, thus reducing overhead to a minimum. .It Supports Microsofts IPCP extentions. Name Server Addresses and NetBIOS Name Server Addresses can be negotiated with clients using the Microsoft .Em PPP stack (ie. Win95, WinNT) .It Runs under BSDI-1.1 and FreeBSD. .El Patches for NeXTSTEP 3.2 are also available on the net. .Sh GETTING STARTED When you first run .Nm you may need to deal with some initial configuration details. First, your kernel should include a tunnel device (the default in FreeBSD 2.0.5 and later). If it doesn't, you'll need to rebuild your kernel with the following line in your kernel configuration file: .Dl pseudo-device tun 1 You should set the numeric field to the maximum number of .Em PPP connections you wish to support. Second, check your .Pa /dev directory for the tunnel device entry .Pa /dev/tun0. If it doesn't exist, you can create it by running "MAKEDEV tun0" .Sh MANUAL DIALING % .Nm User Process PPP written by Toshiharu OHNO. * If you set your hostname and password in .Pa /etc/ppp/ppp.secret , you can't do anything except run the quit and help commands * ppp on "your hostname"> help passwd : Password for security quit : Quit the PPP program help : Display this message ppp on tama> pass * "on" will change to "ON" if you specify the correct password. * ppp ON tama> * You can now specify the device name, speed and parity for your modem, and whether CTS/RTS signalling should be used (CTS/RTS is used by default). If your hardware does not provide CTS/RTS lines (as may happen when you are connected directly to certain ppp-capable terminal servers), .Nm will never send any output through the port; it waits for a signal which never comes. Thus, if you have a direct line and can't seem to make a connection, try turning ctsrts off: * ppp ON tama> set line /dev/cuaa0 ppp ON tama> set speed 38400 ppp ON tama> set parity even ppp ON tama> set ctsrts on ppp ON tama> show modem * Modem related parameters are shown in here * ppp ON tama> * Use term command to talk with your modem * ppp ON tama> term at OK atdt123456 CONNECT login: ppp Password: * PPP started in remote side. When the peer start to talk PPP, the program will detect it automatically and return to command mode. * ppp ON tama> .Nm PPP ON tama> * NOW, you are connected! Note that .Sq PPP in the prompt has changed to capital letters to indicate this. * PPP ON tama> show lcp * You'll see LCP status * PPP ON tama> show ipcp * You'll see IPCP status. At this point, your machine has a host route to the peer. If you want to add a default route entry, then enter the following command. * PPP ON tama> add 0 0 HISADDR * The string .Sq HISADDR represents the IP address of connected peer. * PPP ON tama> * Use network applications (i.e. ping, telnet, ftp) in other windows * PPP ON tama> show log * Gives you some logging messages * PPP ON tama> close * The connection is closed and modem will be disconnected. * ppp ON tama> quit % .Sh AUTOMATIC DIALING To use automatic dialing, you must prepare some Dial and Login chat scripts. See the example definitions in .Pa /etc/ppp/ppp.conf.sample (the format of ppp.conf is pretty simple). .Bl -bullet -compact .It Each line contains one command, label or comment. .It A line starting with a .Sq # character is treated as a comment line. .It A label name has to start in the first column and should be followed by a colon (:). .It A command line must contain a space or tab in the first column. .El Once ppp.conf is ready, specify the destination label name when you invoke .Nm ppp . Commands associated with the destination label are then executed. Note that the commands associated with the .Dq default label are ALWAYS executed. Once the connection is made, you'll find that the .Nm ppp portion of the prompt has changed to .Nm PPP . % ppp pm2 ... ppp ON tama> dial dial OK! login OK! PPP ON tama> If the .Pa /etc/ppp/ppp.linkup file is available, its contents are executed when the .Em PPP connection is established. See the provided example which adds a default route. The string HISADDR represents the IP address of the remote peer. .Sh BACKGROUND DIALING If you want to establish a connection using .Nm ppp non-interactively (such as from a .Xr crontab(5) entry or an .Xr at(1) script) you should use the .Fl background option. You must also specify the destination label in .Pa /etc/ppp/ppp.conf to use. When .Fl background is specified, .Nm attempts to establish the connection. If this attempt fails, .Nm ppp exits immediately with a non-zero exit code. If it succeeds, then .Nm ppp becomes a daemon, and returns an exit status of zero to its caller. The daemon exits automatically if the connection is dropped by the remote system, or it receives a TERM signal. The file .Pa /var/run/ppp.tun0.pid contains the process id number of the .Nm ppp program that is using the tunnel device tun0. .Sh DIAL ON DEMAND To play with demand dialing, you must use the .Fl auto or .Fl ddial option. You must also specify the destination label in .Pa /etc/ppp/ppp.conf to use. It should contain the .Dq ifaddr command to define the remote peer's IP address. (refer to .Pa /etc/ppp/ppp.conf.sample ) % ppp -auto pm2demand ... % When .Fl auto or .Fl ddial is specified, .Nm runs as a daemon but you can still configure or examine its configuration by using the diagnostic port as follows: % telnet localhost 3000 Trying 127.0.0.1... Connected to localhost.spec.co.jp. Escape character is '^]'. User Process PPP. Written by Toshiharu OHNO. Working as auto mode. PPP on tama> show ipcp what ? PPP on tama> pass xxxx PPP ON tama> show ipcp IPCP [OPEND] his side: xxxx .... .Pp Each .Nm daemon has an associated port number which is computed as "3000 + tunnel_device_number". If 3000 is not good base number, edit defs.h in the ppp sources ( .Pa /usr/src/usr.sbin/ppp ) and recompile it. When an outgoing packet is detected, .Nm will perform the dialing action (chat script) and try to connect with the peer. If the connect fails, the default behavior is to wait 30 seconds and then attempt to connect when another outgoing packet is detected. This behavior can be changed with .Bd -literal -offset indent set redial seconds|random[.nseconds|random] [dial_attempts] .Ed .Pp .Sq Seconds is the number of seconds to wait before attempting to connect again. If the argument is .Sq random , the delay period is a random value between 0 and 30 seconds. .Sq Nseconds is the number of seconds to wait before attempting to dial the next number in a list of numbers (see the .Dq set phone command). The default is 3 seconds. Again, if the argument is .Sq random , the delay period is a random value between 0 and 30 seconds. .Sq dial_attempts is the number of times to try to connect for each outgoing packet that is received. The previous value is unchanged if this parameter is omitted. If a value of zero is specified for .Sq dial_attempts , .Nm ppp will keep trying until a connection is made. .Bd -literal -offset indent set redial 10.3 4 .Ed .Pp will attempt to connect 4 times for each outgoing packet that is detected with a 3 second delay between each number and a 10 second delay after all numbers have been tried. If multiple phone numbers are specified, the total number of attempts is still 4 (it does not attempt each number 4 times). Modifying the dial delay is very useful when running .Nm in demand dial mode on both ends of the link. If each end has the same timeout, both ends wind up calling each other at the same time if the link drops and both ends have packets queued. +At some locations, the serial link may not be reliable, and carrier +may be lost at inappropriate times. It is possible to have +.Nm +redial should carrier be unexpectedly lost during a session. +.Bd -literal -offset indent +set reconnect timeout ntries +.Ed + +This command tells ppp to re-establish the connection +.Ar ntries +times on loss of carrier with a pause of +.Ar timeout +seconds before each try. For example, +.Bd -literal -offset indent +set reconnect 3 5 +.Ed + +tells +.Nm +that on an unexpected loss of carrier, it should wait +.Ar 3 +seconds before attempting to reconnect. This may happen up to +.Ar 5 +times before +.Nm +gives up. The default value of ntries is zero (no redial). Care +should be taken with this option. If the local timeout is slightly +longer than the remote timeout, the reconnect feature will always be +triggered (up to the given number of times) after the remote side +times out and hangs up. + If the .Fl background flag is specified, all phone numbers are dialed at most once until a connection is made. The next number redial period specified with the .Dq set redial -command is honoured. +command is honoured, as is the reconnect tries value. To terminate the program, type PPP ON tama> close ppp ON tama> quit all .Pp A simple .Dq quit command will terminate the telnet connection but not the program itself. You must use .Dq quit all to terminate the program as well. .Sh PACKET ALIASING The .Fl alias command line option enables packet aliasing. This allows the ppp host to act as a masquerading gateway for other computers over a local area network. Outgoing IP packets are are aliased so that they appear to come from the ppp host, and incoming packets are de-aliased so that they are routed to the correct machine on the local area network. Packet aliasing allows computers on private, unregistered subnets to have internet access, although they are invisible from the outside world. In general, correct ppp operation should first be verified with packet aliasing disabled. Then, the .Fl alias option should be switched on, and network applications (web browser, telnet, ftp, ping, traceroute) should be checked on the ppp host. Finally, the same or similar applications should be checked on other computers in the LAN. If network applications work correctly on the ppp host, but not on other machines in the LAN, then the masquerading software is working properly, but the host is either not forwarding or possibly receiving IP packets. Check that IP forwarding is enabled in /etc/sysconfig and that other machines have designated the ppp host as the gateway for the LAN. .Sh PACKET FILTERING This implementation supports packet filtering. There are three kinds of filters: ifilter, ofilter and dfilter. Here are the basics: .Bl -bullet -compact .It A filter definition has the following syntax: set filter-name rule-no action [src_addr/src_width] [dst_addr/dst_width] [proto [src [lt|eq|gt] port ]] [dst [lt|eq|gt] port] [estab] .Bl -enum .It .Sq filter-name should be one of ifilter, ofilter, or dfilter. .It There are two actions: .Sq permit and .Sq deny . If a given packet matches the rule, the associated action is taken immediately. .It .Sq src_width and .Sq dst_width work like a netmask to represent an address range. .It .Sq proto must be one of icmp, udp or tcp. .It .Sq port number can be specified by number and service name from .Pa /etc/services . .El .It Each filter can hold up to 20 rules, starting from rule 0. The entire rule set is not effective until rule 0 is defined. .It If no rule is matched to a packet, that packet will be discarded (blocked). .It Use .Dq set filter-name -1 to flush all rules. .El See .Pa /etc/ppp/ppp.conf.filter.example . .Sh RECEIVING INCOMING PPP CONNECTIONS (Method 1) To handle an incoming .Em PPP connection request, follow these steps: .Bl -enum .It Make sure the modem and (optionally) .Pa /etc/rc.serial is configured correctly. .Bl -bullet -compact .It Use Hardware Handshake (CTS/RTS) for flow control. .It Modem should be set to NO echo back (ATE0) and NO results string (ATQ1). .El .It Edit .Pa /etc/ttys to enable a getty on the port where the modem is attached. For example: .Dl ttyd1 "/usr/libexec/getty std.38400" dialup on secure Don't forget to send a HUP signal to the init process to start the getty. .Dl # kill -HUP 1 .It Prepare an account for the incoming user. .Bd -literal ppp:xxxx:66:66:PPP Login User:/home/ppp:/usr/local/bin/ppplogin .Ed .It Create a .Pa /usr/local/bin/ppplogin file with the following contents: .Bd -literal -offset indent #!/bin/sh -p exec /usr/sbin/ppp -direct .Ed (You can specify a label name for further control.) .Pp Direct mode ( .Fl direct ) lets .Nm work with stdin and stdout. You can also telnet to port 3000 to get command mode control in the same manner as client-side .Nm. .It Optional support for Microsoft's IPCP Name Server and NetBIOS Name Server negotiation can be enabled use .Dq enable msext and .Dq set ns pri-addr [sec-addr] along with .Dq set nbns pri-addr [sec-addr] in your ppp.conf file .El .Sh RECEIVING INCOMING PPP CONNECTIONS (Method 2) This method differs in that it recommends the use of .Em mgetty+sendfax to handle the modem connections. The latest version 0.99 can be compiled with the .Dq AUTO_PPP option to allow detection of clients speaking PPP to the login prompt. Follow these steps: .Bl -enum .It Get, configure, and install mgetty+sendfax v0.99 or later (beta) making sure you have used the AUTO_PPP option. .It Edit .Pa /etc/ttys to enable a mgetty on the port where the modem is attached. For example: .Dl cuaa1 "/usr/local/sbin/mgetty -s 57600" dialup on .It Prepare an account for the incoming user. .Bd -literal Pfred:xxxx:66:66:Fred's PPP:/home/ppp:/etc/ppp/ppp-dialup .Ed .It Examine the files .Pa /etc/ppp/sample.ppp-dialup .Pa /etc/ppp/sample.ppp-pap-dialup and .Pa /etc/ppp/sample.ppp.conf for ideas. ppp-pap-dialup is supposed to be called from .Pa /usr/local/etc/mgetty+sendfax/login.conf from a line like .Dl /AutoPPP/ - - /etc/ppp/ppp-pap-dialup .El .Sh SETTING IDLE, LINE QUALITY REQUEST, RETRY TIMER To check/set idletimer, use the .Dq show timeout and .Dq set timeout [lqrtimer [retrytimer]] commands. Ex: .Dl ppp ON tama> set timeout 600 The timeout period is measured in seconds, the default values for which are timeout = 180 or 3 min, lqrtimer = 30sec and retrytimer = 3sec. To disable the idle timer function, use the command .Dq set timeout 0 . In .Fl auto mode, an idle timeout causes the .Em PPP session to be closed, though the .Nm program itself remains running. Another trigger packet will cause it to attempt to reestablish the link. .Sh Predictor-1 compression This version supports CCP and Predictor type 1 compression based on the current IETF-draft specs. As a default behavior, .Nm will attempt to use (or be willing to accept) this capability when the peer agrees (or requests it). To disable CCP/predictor functionality completely, use the .Dq disable pred1 and .Dq deny pred1 commands. .Sh Controlling IP address .Nm uses IPCP to negotiate IP addresses. Each side of the connection specifies the IP address that it's willing to use, and if the requested IP address is acceptable then .Nm returns ACK to the requester. Otherwise, .Nm returns NAK to suggest that the peer use a different IP address. When both sides of the connection agree to accept the received request (and send ACK), IPCP is set to the open state and a network level connection is established. To control this IPCP behavior, this implementation has the .Dq set ifaddr command for defining the local and remote IP address: .Nm set ifaddr .Op src_addr Op dst_addr Op netmask Op trg_addr Where, .Sq src_addr is the IP address that the local side is willing to use and .Sq dst_addr is the IP address which the remote side should use. .Sq netmask is interface netmask. .Sq trg_addr is the IP address which used in address negotiation. Ex: .Dl set ifaddr 192.244.177.38 192.244.177.2 255.255.255.0 The above specification means: .Bl -bullet -compact .It I strongly want to use 192.244.177.38 as my IP address, and I'll disagree if the peer suggests that I use another address. .It I strongly insist that peer use 192.244.177.2 as own side address and don't permit it to use any IP address but 192.244.177.2. When peer request another IP address, I always suggest that it use 192.244.177.2. .It My interface netmask will be 255.255.255.0. .It This is all fine when each side has a pre-determined IP address, however it is often the case that one side is acting as a server which controls all IP addresses and the other side should obey the direction from it. .El In order to allow more flexible behavior, `ifaddr' variable allows the user to specify IP address more loosely: .Dl set ifaddr 192.244.177.38/24 192.244.177.2/20 A number followed by a slash (/) represent the number of bits significant in the IP address. The above example signifies that: .Bl -bullet -compact .It I'd like to use 192.244.177.38 as my address if it is possible, but I'll also accept any IP address between 192.244.177.0 and 192.244.177.255. .It I'd like to make him use 192.244.177.2 as his own address, but I'll also permit him to use any IP address between 192.244.176.0 and 192.244.191.255. .It As you may have already noticed, 192.244.177.2 is equivalent to saying 192.244.177.2/32. .It As an exception, 0 is equivalent to 0.0.0.0/0, meaning that I have no preferred IP address and will obey the remote peer's selection. .It 192.244.177.2/0 means that I'll accept/permit any IP address but I'll try to insist that 192.244.177.2 be used first. .El .Sh Connecting with your service provider The following steps should be taken when connecting to your ISP: .Bl -enum .It Describe your provider's phone number(s) in the dial script using the .Dq set phone command. This command allows you to set multiple phone numbers for dialing and redialing separated by a colon (:). For example: .Bd -literal -offset indent set phone "1234567:2345678" .Ed .Pp Here, the first number is attempted. If the connection fails, the second number is attempted after the next number redial period. If the second number also fails, the first is tried again after the redial period has expired. The selected phone number is substituted for the \\T string in the .Dq set dial command (see below). .It Set up your redial requirements using .Dq set redial . For example, if you have a bad telephone line or your provider is usually engaged (not so common these days), you may want to specify the following: .Bd -literal -offset indent set redial 10 4 .Ed .Pp This says that up to 4 phone calls should be attempted with a pause of 10 seconds before dialing the first number again. .It Describe your login procedure using the .Dq set dial and .Dq set login commands. The .Dq set dial command is used to talk to your modem and establish a link with your ISP, for example: .Bd -literal -offset indent set dial "ABORT BUSY ABORT NO\\\\sCARRIER TIMEOUT 4 \\"\\" ATZ OK-ATZ-OK ATDT\\\\T TIMEOUT 60 CONNECT" .Ed .Pp This modem "chat" string means: .Bl -bullet .It Abort if the string "BUSY" or "NO CARRIER" are received. .It Set the timeout to 4. .It Expect nothing. .It Send ATZ. .It Expect OK. If that's not received, send ATZ and expect OK. .It Send ATDTxxxxxxx where xxxxxxx is the next number in the phone list from above. .It Set the timeout to 60. .It Wait for the CONNECT string. .El Once the connection is established, the login script is executed. This script is written in the same style as the dial script: .Bd -literal -offset indent set login "TIMEOUT 15 login:-\\\\r-login: awfulhak word: xxx ocol: PPP HELLO" .Ed .Pp This login "chat" string means: .Bl -bullet .It Set the timeout to 15 seconds. .It Expect "login:". If it's not received, send a carriage return and expect "login:" again. .It Send "awfulhak" .It Expect "word:" (the tail end of a "Password:" prompt). .It Send "xxx". .It Expect "ocol:" (the tail end of a "Protocol:" prompt). .It Send "PPP". .It Expect "HELLO". .El .Pp Login scripts vary greatly between ISPs. .It Use .Dq set line and .Dq set sp to specify your serial line and speed, for example: .Bd -literal -offset indent set line /dev/cuaa0 set sp 115200 .Ed .Pp Cuaa0 is the first serial port on FreeBSD. Cuaa1 is the second etc. A speed of 115200 should be specified if you have a modem capable of bit rates of 28800 or more. In general, the serial speed should be about four times the modem speed. .It Use .Dq set ifaddr command to define the IP address. .Bl -bullet .It If you know what IP address your provider uses, then use it as the remote address, otherwise choose something like 10.0.0.2/0 (see below). .It If your provider has assigned a particular IP address to you, then use it as your address. .It If your provider assigns your address dynamically, choose a suitably unobtrusive and unspecific IP number as your address. 10.0.0.1/0 would be appropriate. The bit after the / specifies how many bits of the address you consider to be important, so if you wanted to insist on something in the class C network 1.2.3.0, you could specify 1.2.3.0/24. .El .Pp An example for a connection where you don't know your IP number or your ISPs IP number would be: .Bd -literal -offset indent set ifaddr 10.0.0.1/0 10.0.0.2/0 .Ed .It In most cases, your ISP will also be your default router. If this is the case, add the lines .Bd -literal -offset indent delete ALL add 0 0 HISADDR .Ed .Pp to .Pa ppp.conf . .Pp This tells .Nm ppp to delete all routing entries already made by .Nm ppp , then to add a default route to HISADDR. HISADDR is a macro meaning the "other side"s IP number. .Pp If you're using dynamic IP numbers, you must also put these two lines in the .Pa ppp.linkup file. Then, once the link has been established and .Nm ppp knows the actual IP numbers in use, all previous (and probably incorrect) entries are deleted and a default to the correct IP number is added. Use the same label as the one used in .Pa ppp.conf . .Pp If commands are being typed interactively, the only requirement is to type .Bd -literal -offset indent add 0 0 HISADDR .Ed .Pp after a successful dial. .It If your provider requests that you use PAP/CHAP authentication methods, add the next lines to your .Pa ppp.conf file: .Bd -literal -offset indent enable pap (or enable chap) disable chap (or disable pap) set authname MyName set authkey MyPassword .Ed .It It is also worth adding the following line: .Bd -literal -offset indent set openmode active .Ed .Pp This tells .Nm ppp to initiate LCP. Without this line, there's a possibility of both sides of the connection just sitting there and looking at eachother rather than communicating. .El Please refer to .Pa /etc/ppp/ppp.conf.sample and .Pa /etc/ppp/ppp.linkup.sample for some real examples. The pmdemand label should be appropriate for most ISPs. .Sh Logging facility .Nm is able to generate the following log info into .Pa /var/log/ppp.log : .Bl -column SMMMMMM -offset indent -compat .It Li Phase Phase transition log output .It Li Chat Generate Chat script trace log .It Li Connect Generate complete Chat log .It Li Carrier Log Chat lines with 'CARRIER' .It Li LQM Generate LQR report .It Li LCP Generate LCP/IPCP packet trace .It Li Link Log address assignments and link up/down events .It Li TCP/IP Dump TCP/IP packet .It Li HDLC Dump HDLC packet in hex .It Li Async Dump async level packet in hex .El The .Dq set debug command allows you to set logging output level, of which multiple levels can be specified. The default is equivalent to .Dq set debug carrier link phase . If a HUP signal is received, the log file is closed and re-opened to facilitate log file rotation. .Sh MORE DETAILS .Bl -bullet -compact .It Please read the Japanese doc for complete explanation. It may not be useful for non-japanese readers, but examples in the document may help you to guess. .It Please read example configuration files. .It Use .Dq help , .Dq show ? , .Dq set ? and .Dq set ? commands. .It NetBSD and BSDI-1.0 were supported in previous releases but are no longer supported in this release. Please contact the author if you need old driver code. .El .Sh FILES .Nm refers to three files: ppp.conf, ppp.linkup and ppp.secret. These files are placed in .Pa /etc/ppp , but the user can create his own files under his $HOME directory as .Pa .ppp.conf , .Pa .ppp.linkup and .Pa .ppp.secret. .Nm will always try to consult the user's personal setup first. .Bl -tag -width flag .Pa $HOME/ppp/.ppp.[conf|linkup|secret] User dependent configuration files. .Pa /etc/ppp/ppp.conf System default configuration file. .Pa /etc/ppp/ppp.secret An authorization file for each system. .Pa /etc/ppp/ppp.linkup A file to check when .Nm establishes a network level connection. .Pa /var/log/ppp.log Logging and debugging information file. .Pa /var/spool/lock/Lck..* tty port locking file. .Pa /var/run/PPP.system Holds the pid for ppp -auto system. .Pa /var/run/ppp.tun0.pid The process id (pid) of the ppp program connected to the ppp0 device. .Pa /etc/services Get port number if port number is using service name. .El .Sh SEE ALSO .Xr chat 8 , .Xr pppd 8 .Sh HISTORY This program was submitted in FreeBSD-2.0.5 Atsushi Murai (amurai@spec.co.jp). .Sh AUTHORS Toshiharu OHNO (tony-o@iij.ad.jp) diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4 index 26ad29e84eae..f4431ee16183 100644 --- a/usr.sbin/ppp/ppp.8.m4 +++ b/usr.sbin/ppp/ppp.8.m4 @@ -1,1104 +1,1135 @@ .\" manual page [] for ppp 0.94 beta2 + alpha -.\" $Id: ppp.8,v 1.28 1997/04/13 00:54:45 brian Exp $ +.\" $Id: ppp.8,v 1.29 1997/04/14 23:48:17 brian Exp $ .Dd 20 September 1995 .Os FreeBSD .Dt PPP 8 .Sh NAME .Nm ppp .Nd Point to Point Protocol (aka iijppp) .Sh SYNOPSIS .Nm .Op Fl auto | background | ddial | direct | dedicated .Op Fl alias .Op Ar system .Sh DESCRIPTION This is a user process .Em PPP software package. Normally, .Em PPP is implemented as a part of the kernel (e.g. as managed by pppd) and it's thus somewhat hard to debug and/or modify its behavior. However, in this implementation .Em PPP is done as a user process with the help of the tunnel device driver (tun). .Sh Major Features .Bl -diag .It Provides interactive user interface. Using its command mode, the user can easily enter commands to establish the connection with the remote end, check the status of connection and close the connection. All functions can also be optionally password protected for security. .It Supports both manual and automatic dialing. Interactive mode has a .Dq term command which enables you to talk to your modem directly. When your modem is connected to the remote peer and it starts to talk .Em PPP , the .Em PPP software detects it and switches to packet mode automatically. Once you have determined the proper sequence for connecting with the remote host, you can write a chat script to define the necessary dialing and login procedure for later convenience. .It Supports on-demand dialup capability. By using auto mode, .Nm will act as a daemon and wait for a packet to be sent over the .Em PPP link. When this happens, the daemon automatically dials and establishes the connection. In almost the same manner ddial mode (dedicated or demon dialing) also automatically dials and establishes the connection. However, it differs in that it will dial the remote site any time it detects the link is down, even if there are no packets to be sent. This mode is useful for full-time connections who worry less about line charges and more about being connected full time. .It Supports packet aliasing. Packet aliasing, more commonly known as masquerading, allows computers on a private, unregistered network to access the internet. The .Em PPP host acts as a masquerading gateway. IP addresses as well as TCP and UDP port numbers are aliased for outgoing packets and de-aliased for returning packets. .It Supports background PPP connections. In background mode, if .Nm successfully establishes the connection, it will become a daemon. Otherwise, it will exit with an error. .It Supports server-side PPP connections. Can act as server which accepts incoming .Em PPP connections. .It Supports PAP and CHAP authentication. .It Supports Proxy Arp. When .Em PPP is set up as server, you can also configure it to do proxy arp for your connection. .It Supports packet filtering. User can define four kinds of filters: .Em ifilter for incoming packets, .Em ofilter for outgoing packets, .Em dfilter to define a dialing trigger packet and .Em afilter for keeping a connection alive with the trigger packet. .It Tunnel driver supports bpf. The user can use .Xr tcpdump 1 to check the packet flow over the .Em PPP link. .It Supports PPP over TCP capability. .It Supports IETF draft Predictor-1 compression. .Nm supports not only VJ-compression but also Predictor-1 compression. Normally, a modem has built-in compression (e.g. v42.bis) and the system may receive higher data rates from it as a result of such compression. While this is generally a good thing in most other situations, this higher speed data imposes a penalty on the system by increasing the number of serial interrupts the system has to process in talking to the modem and also increases latency. Unlike VJ-compression, Predictor-1 compression pre-compresses .Em all data flowing through the link, thus reducing overhead to a minimum. .It Supports Microsofts IPCP extentions. Name Server Addresses and NetBIOS Name Server Addresses can be negotiated with clients using the Microsoft .Em PPP stack (ie. Win95, WinNT) .It Runs under BSDI-1.1 and FreeBSD. .El Patches for NeXTSTEP 3.2 are also available on the net. .Sh GETTING STARTED When you first run .Nm you may need to deal with some initial configuration details. First, your kernel should include a tunnel device (the default in FreeBSD 2.0.5 and later). If it doesn't, you'll need to rebuild your kernel with the following line in your kernel configuration file: .Dl pseudo-device tun 1 You should set the numeric field to the maximum number of .Em PPP connections you wish to support. Second, check your .Pa /dev directory for the tunnel device entry .Pa /dev/tun0. If it doesn't exist, you can create it by running "MAKEDEV tun0" .Sh MANUAL DIALING % .Nm User Process PPP written by Toshiharu OHNO. * If you set your hostname and password in .Pa /etc/ppp/ppp.secret , you can't do anything except run the quit and help commands * ppp on "your hostname"> help passwd : Password for security quit : Quit the PPP program help : Display this message ppp on tama> pass * "on" will change to "ON" if you specify the correct password. * ppp ON tama> * You can now specify the device name, speed and parity for your modem, and whether CTS/RTS signalling should be used (CTS/RTS is used by default). If your hardware does not provide CTS/RTS lines (as may happen when you are connected directly to certain ppp-capable terminal servers), .Nm will never send any output through the port; it waits for a signal which never comes. Thus, if you have a direct line and can't seem to make a connection, try turning ctsrts off: * ppp ON tama> set line /dev/cuaa0 ppp ON tama> set speed 38400 ppp ON tama> set parity even ppp ON tama> set ctsrts on ppp ON tama> show modem * Modem related parameters are shown in here * ppp ON tama> * Use term command to talk with your modem * ppp ON tama> term at OK atdt123456 CONNECT login: ppp Password: * PPP started in remote side. When the peer start to talk PPP, the program will detect it automatically and return to command mode. * ppp ON tama> .Nm PPP ON tama> * NOW, you are connected! Note that .Sq PPP in the prompt has changed to capital letters to indicate this. * PPP ON tama> show lcp * You'll see LCP status * PPP ON tama> show ipcp * You'll see IPCP status. At this point, your machine has a host route to the peer. If you want to add a default route entry, then enter the following command. * PPP ON tama> add 0 0 HISADDR * The string .Sq HISADDR represents the IP address of connected peer. * PPP ON tama> * Use network applications (i.e. ping, telnet, ftp) in other windows * PPP ON tama> show log * Gives you some logging messages * PPP ON tama> close * The connection is closed and modem will be disconnected. * ppp ON tama> quit % .Sh AUTOMATIC DIALING To use automatic dialing, you must prepare some Dial and Login chat scripts. See the example definitions in .Pa /etc/ppp/ppp.conf.sample (the format of ppp.conf is pretty simple). .Bl -bullet -compact .It Each line contains one command, label or comment. .It A line starting with a .Sq # character is treated as a comment line. .It A label name has to start in the first column and should be followed by a colon (:). .It A command line must contain a space or tab in the first column. .El Once ppp.conf is ready, specify the destination label name when you invoke .Nm ppp . Commands associated with the destination label are then executed. Note that the commands associated with the .Dq default label are ALWAYS executed. Once the connection is made, you'll find that the .Nm ppp portion of the prompt has changed to .Nm PPP . % ppp pm2 ... ppp ON tama> dial dial OK! login OK! PPP ON tama> If the .Pa /etc/ppp/ppp.linkup file is available, its contents are executed when the .Em PPP connection is established. See the provided example which adds a default route. The string HISADDR represents the IP address of the remote peer. .Sh BACKGROUND DIALING If you want to establish a connection using .Nm ppp non-interactively (such as from a .Xr crontab(5) entry or an .Xr at(1) script) you should use the .Fl background option. You must also specify the destination label in .Pa /etc/ppp/ppp.conf to use. When .Fl background is specified, .Nm attempts to establish the connection. If this attempt fails, .Nm ppp exits immediately with a non-zero exit code. If it succeeds, then .Nm ppp becomes a daemon, and returns an exit status of zero to its caller. The daemon exits automatically if the connection is dropped by the remote system, or it receives a TERM signal. The file .Pa /var/run/ppp.tun0.pid contains the process id number of the .Nm ppp program that is using the tunnel device tun0. .Sh DIAL ON DEMAND To play with demand dialing, you must use the .Fl auto or .Fl ddial option. You must also specify the destination label in .Pa /etc/ppp/ppp.conf to use. It should contain the .Dq ifaddr command to define the remote peer's IP address. (refer to .Pa /etc/ppp/ppp.conf.sample ) % ppp -auto pm2demand ... % When .Fl auto or .Fl ddial is specified, .Nm runs as a daemon but you can still configure or examine its configuration by using the diagnostic port as follows: % telnet localhost 3000 Trying 127.0.0.1... Connected to localhost.spec.co.jp. Escape character is '^]'. User Process PPP. Written by Toshiharu OHNO. Working as auto mode. PPP on tama> show ipcp what ? PPP on tama> pass xxxx PPP ON tama> show ipcp IPCP [OPEND] his side: xxxx .... .Pp Each .Nm daemon has an associated port number which is computed as "3000 + tunnel_device_number". If 3000 is not good base number, edit defs.h in the ppp sources ( .Pa /usr/src/usr.sbin/ppp ) and recompile it. When an outgoing packet is detected, .Nm will perform the dialing action (chat script) and try to connect with the peer. If the connect fails, the default behavior is to wait 30 seconds and then attempt to connect when another outgoing packet is detected. This behavior can be changed with .Bd -literal -offset indent set redial seconds|random[.nseconds|random] [dial_attempts] .Ed .Pp .Sq Seconds is the number of seconds to wait before attempting to connect again. If the argument is .Sq random , the delay period is a random value between 0 and 30 seconds. .Sq Nseconds is the number of seconds to wait before attempting to dial the next number in a list of numbers (see the .Dq set phone command). The default is 3 seconds. Again, if the argument is .Sq random , the delay period is a random value between 0 and 30 seconds. .Sq dial_attempts is the number of times to try to connect for each outgoing packet that is received. The previous value is unchanged if this parameter is omitted. If a value of zero is specified for .Sq dial_attempts , .Nm ppp will keep trying until a connection is made. .Bd -literal -offset indent set redial 10.3 4 .Ed .Pp will attempt to connect 4 times for each outgoing packet that is detected with a 3 second delay between each number and a 10 second delay after all numbers have been tried. If multiple phone numbers are specified, the total number of attempts is still 4 (it does not attempt each number 4 times). Modifying the dial delay is very useful when running .Nm in demand dial mode on both ends of the link. If each end has the same timeout, both ends wind up calling each other at the same time if the link drops and both ends have packets queued. +At some locations, the serial link may not be reliable, and carrier +may be lost at inappropriate times. It is possible to have +.Nm +redial should carrier be unexpectedly lost during a session. +.Bd -literal -offset indent +set reconnect timeout ntries +.Ed + +This command tells ppp to re-establish the connection +.Ar ntries +times on loss of carrier with a pause of +.Ar timeout +seconds before each try. For example, +.Bd -literal -offset indent +set reconnect 3 5 +.Ed + +tells +.Nm +that on an unexpected loss of carrier, it should wait +.Ar 3 +seconds before attempting to reconnect. This may happen up to +.Ar 5 +times before +.Nm +gives up. The default value of ntries is zero (no redial). Care +should be taken with this option. If the local timeout is slightly +longer than the remote timeout, the reconnect feature will always be +triggered (up to the given number of times) after the remote side +times out and hangs up. + If the .Fl background flag is specified, all phone numbers are dialed at most once until a connection is made. The next number redial period specified with the .Dq set redial -command is honoured. +command is honoured, as is the reconnect tries value. To terminate the program, type PPP ON tama> close ppp ON tama> quit all .Pp A simple .Dq quit command will terminate the telnet connection but not the program itself. You must use .Dq quit all to terminate the program as well. .Sh PACKET ALIASING The .Fl alias command line option enables packet aliasing. This allows the ppp host to act as a masquerading gateway for other computers over a local area network. Outgoing IP packets are are aliased so that they appear to come from the ppp host, and incoming packets are de-aliased so that they are routed to the correct machine on the local area network. Packet aliasing allows computers on private, unregistered subnets to have internet access, although they are invisible from the outside world. In general, correct ppp operation should first be verified with packet aliasing disabled. Then, the .Fl alias option should be switched on, and network applications (web browser, telnet, ftp, ping, traceroute) should be checked on the ppp host. Finally, the same or similar applications should be checked on other computers in the LAN. If network applications work correctly on the ppp host, but not on other machines in the LAN, then the masquerading software is working properly, but the host is either not forwarding or possibly receiving IP packets. Check that IP forwarding is enabled in /etc/sysconfig and that other machines have designated the ppp host as the gateway for the LAN. .Sh PACKET FILTERING This implementation supports packet filtering. There are three kinds of filters: ifilter, ofilter and dfilter. Here are the basics: .Bl -bullet -compact .It A filter definition has the following syntax: set filter-name rule-no action [src_addr/src_width] [dst_addr/dst_width] [proto [src [lt|eq|gt] port ]] [dst [lt|eq|gt] port] [estab] .Bl -enum .It .Sq filter-name should be one of ifilter, ofilter, or dfilter. .It There are two actions: .Sq permit and .Sq deny . If a given packet matches the rule, the associated action is taken immediately. .It .Sq src_width and .Sq dst_width work like a netmask to represent an address range. .It .Sq proto must be one of icmp, udp or tcp. .It .Sq port number can be specified by number and service name from .Pa /etc/services . .El .It Each filter can hold up to 20 rules, starting from rule 0. The entire rule set is not effective until rule 0 is defined. .It If no rule is matched to a packet, that packet will be discarded (blocked). .It Use .Dq set filter-name -1 to flush all rules. .El See .Pa /etc/ppp/ppp.conf.filter.example . .Sh RECEIVING INCOMING PPP CONNECTIONS (Method 1) To handle an incoming .Em PPP connection request, follow these steps: .Bl -enum .It Make sure the modem and (optionally) .Pa /etc/rc.serial is configured correctly. .Bl -bullet -compact .It Use Hardware Handshake (CTS/RTS) for flow control. .It Modem should be set to NO echo back (ATE0) and NO results string (ATQ1). .El .It Edit .Pa /etc/ttys to enable a getty on the port where the modem is attached. For example: .Dl ttyd1 "/usr/libexec/getty std.38400" dialup on secure Don't forget to send a HUP signal to the init process to start the getty. .Dl # kill -HUP 1 .It Prepare an account for the incoming user. .Bd -literal ppp:xxxx:66:66:PPP Login User:/home/ppp:/usr/local/bin/ppplogin .Ed .It Create a .Pa /usr/local/bin/ppplogin file with the following contents: .Bd -literal -offset indent #!/bin/sh -p exec /usr/sbin/ppp -direct .Ed (You can specify a label name for further control.) .Pp Direct mode ( .Fl direct ) lets .Nm work with stdin and stdout. You can also telnet to port 3000 to get command mode control in the same manner as client-side .Nm. .It Optional support for Microsoft's IPCP Name Server and NetBIOS Name Server negotiation can be enabled use .Dq enable msext and .Dq set ns pri-addr [sec-addr] along with .Dq set nbns pri-addr [sec-addr] in your ppp.conf file .El .Sh RECEIVING INCOMING PPP CONNECTIONS (Method 2) This method differs in that it recommends the use of .Em mgetty+sendfax to handle the modem connections. The latest version 0.99 can be compiled with the .Dq AUTO_PPP option to allow detection of clients speaking PPP to the login prompt. Follow these steps: .Bl -enum .It Get, configure, and install mgetty+sendfax v0.99 or later (beta) making sure you have used the AUTO_PPP option. .It Edit .Pa /etc/ttys to enable a mgetty on the port where the modem is attached. For example: .Dl cuaa1 "/usr/local/sbin/mgetty -s 57600" dialup on .It Prepare an account for the incoming user. .Bd -literal Pfred:xxxx:66:66:Fred's PPP:/home/ppp:/etc/ppp/ppp-dialup .Ed .It Examine the files .Pa /etc/ppp/sample.ppp-dialup .Pa /etc/ppp/sample.ppp-pap-dialup and .Pa /etc/ppp/sample.ppp.conf for ideas. ppp-pap-dialup is supposed to be called from .Pa /usr/local/etc/mgetty+sendfax/login.conf from a line like .Dl /AutoPPP/ - - /etc/ppp/ppp-pap-dialup .El .Sh SETTING IDLE, LINE QUALITY REQUEST, RETRY TIMER To check/set idletimer, use the .Dq show timeout and .Dq set timeout [lqrtimer [retrytimer]] commands. Ex: .Dl ppp ON tama> set timeout 600 The timeout period is measured in seconds, the default values for which are timeout = 180 or 3 min, lqrtimer = 30sec and retrytimer = 3sec. To disable the idle timer function, use the command .Dq set timeout 0 . In .Fl auto mode, an idle timeout causes the .Em PPP session to be closed, though the .Nm program itself remains running. Another trigger packet will cause it to attempt to reestablish the link. .Sh Predictor-1 compression This version supports CCP and Predictor type 1 compression based on the current IETF-draft specs. As a default behavior, .Nm will attempt to use (or be willing to accept) this capability when the peer agrees (or requests it). To disable CCP/predictor functionality completely, use the .Dq disable pred1 and .Dq deny pred1 commands. .Sh Controlling IP address .Nm uses IPCP to negotiate IP addresses. Each side of the connection specifies the IP address that it's willing to use, and if the requested IP address is acceptable then .Nm returns ACK to the requester. Otherwise, .Nm returns NAK to suggest that the peer use a different IP address. When both sides of the connection agree to accept the received request (and send ACK), IPCP is set to the open state and a network level connection is established. To control this IPCP behavior, this implementation has the .Dq set ifaddr command for defining the local and remote IP address: .Nm set ifaddr .Op src_addr Op dst_addr Op netmask Op trg_addr Where, .Sq src_addr is the IP address that the local side is willing to use and .Sq dst_addr is the IP address which the remote side should use. .Sq netmask is interface netmask. .Sq trg_addr is the IP address which used in address negotiation. Ex: .Dl set ifaddr 192.244.177.38 192.244.177.2 255.255.255.0 The above specification means: .Bl -bullet -compact .It I strongly want to use 192.244.177.38 as my IP address, and I'll disagree if the peer suggests that I use another address. .It I strongly insist that peer use 192.244.177.2 as own side address and don't permit it to use any IP address but 192.244.177.2. When peer request another IP address, I always suggest that it use 192.244.177.2. .It My interface netmask will be 255.255.255.0. .It This is all fine when each side has a pre-determined IP address, however it is often the case that one side is acting as a server which controls all IP addresses and the other side should obey the direction from it. .El In order to allow more flexible behavior, `ifaddr' variable allows the user to specify IP address more loosely: .Dl set ifaddr 192.244.177.38/24 192.244.177.2/20 A number followed by a slash (/) represent the number of bits significant in the IP address. The above example signifies that: .Bl -bullet -compact .It I'd like to use 192.244.177.38 as my address if it is possible, but I'll also accept any IP address between 192.244.177.0 and 192.244.177.255. .It I'd like to make him use 192.244.177.2 as his own address, but I'll also permit him to use any IP address between 192.244.176.0 and 192.244.191.255. .It As you may have already noticed, 192.244.177.2 is equivalent to saying 192.244.177.2/32. .It As an exception, 0 is equivalent to 0.0.0.0/0, meaning that I have no preferred IP address and will obey the remote peer's selection. .It 192.244.177.2/0 means that I'll accept/permit any IP address but I'll try to insist that 192.244.177.2 be used first. .El .Sh Connecting with your service provider The following steps should be taken when connecting to your ISP: .Bl -enum .It Describe your provider's phone number(s) in the dial script using the .Dq set phone command. This command allows you to set multiple phone numbers for dialing and redialing separated by a colon (:). For example: .Bd -literal -offset indent set phone "1234567:2345678" .Ed .Pp Here, the first number is attempted. If the connection fails, the second number is attempted after the next number redial period. If the second number also fails, the first is tried again after the redial period has expired. The selected phone number is substituted for the \\T string in the .Dq set dial command (see below). .It Set up your redial requirements using .Dq set redial . For example, if you have a bad telephone line or your provider is usually engaged (not so common these days), you may want to specify the following: .Bd -literal -offset indent set redial 10 4 .Ed .Pp This says that up to 4 phone calls should be attempted with a pause of 10 seconds before dialing the first number again. .It Describe your login procedure using the .Dq set dial and .Dq set login commands. The .Dq set dial command is used to talk to your modem and establish a link with your ISP, for example: .Bd -literal -offset indent set dial "ABORT BUSY ABORT NO\\\\sCARRIER TIMEOUT 4 \\"\\" ATZ OK-ATZ-OK ATDT\\\\T TIMEOUT 60 CONNECT" .Ed .Pp This modem "chat" string means: .Bl -bullet .It Abort if the string "BUSY" or "NO CARRIER" are received. .It Set the timeout to 4. .It Expect nothing. .It Send ATZ. .It Expect OK. If that's not received, send ATZ and expect OK. .It Send ATDTxxxxxxx where xxxxxxx is the next number in the phone list from above. .It Set the timeout to 60. .It Wait for the CONNECT string. .El Once the connection is established, the login script is executed. This script is written in the same style as the dial script: .Bd -literal -offset indent set login "TIMEOUT 15 login:-\\\\r-login: awfulhak word: xxx ocol: PPP HELLO" .Ed .Pp This login "chat" string means: .Bl -bullet .It Set the timeout to 15 seconds. .It Expect "login:". If it's not received, send a carriage return and expect "login:" again. .It Send "awfulhak" .It Expect "word:" (the tail end of a "Password:" prompt). .It Send "xxx". .It Expect "ocol:" (the tail end of a "Protocol:" prompt). .It Send "PPP". .It Expect "HELLO". .El .Pp Login scripts vary greatly between ISPs. .It Use .Dq set line and .Dq set sp to specify your serial line and speed, for example: .Bd -literal -offset indent set line /dev/cuaa0 set sp 115200 .Ed .Pp Cuaa0 is the first serial port on FreeBSD. Cuaa1 is the second etc. A speed of 115200 should be specified if you have a modem capable of bit rates of 28800 or more. In general, the serial speed should be about four times the modem speed. .It Use .Dq set ifaddr command to define the IP address. .Bl -bullet .It If you know what IP address your provider uses, then use it as the remote address, otherwise choose something like 10.0.0.2/0 (see below). .It If your provider has assigned a particular IP address to you, then use it as your address. .It If your provider assigns your address dynamically, choose a suitably unobtrusive and unspecific IP number as your address. 10.0.0.1/0 would be appropriate. The bit after the / specifies how many bits of the address you consider to be important, so if you wanted to insist on something in the class C network 1.2.3.0, you could specify 1.2.3.0/24. .El .Pp An example for a connection where you don't know your IP number or your ISPs IP number would be: .Bd -literal -offset indent set ifaddr 10.0.0.1/0 10.0.0.2/0 .Ed .It In most cases, your ISP will also be your default router. If this is the case, add the lines .Bd -literal -offset indent delete ALL add 0 0 HISADDR .Ed .Pp to .Pa ppp.conf . .Pp This tells .Nm ppp to delete all routing entries already made by .Nm ppp , then to add a default route to HISADDR. HISADDR is a macro meaning the "other side"s IP number. .Pp If you're using dynamic IP numbers, you must also put these two lines in the .Pa ppp.linkup file. Then, once the link has been established and .Nm ppp knows the actual IP numbers in use, all previous (and probably incorrect) entries are deleted and a default to the correct IP number is added. Use the same label as the one used in .Pa ppp.conf . .Pp If commands are being typed interactively, the only requirement is to type .Bd -literal -offset indent add 0 0 HISADDR .Ed .Pp after a successful dial. .It If your provider requests that you use PAP/CHAP authentication methods, add the next lines to your .Pa ppp.conf file: .Bd -literal -offset indent enable pap (or enable chap) disable chap (or disable pap) set authname MyName set authkey MyPassword .Ed .It It is also worth adding the following line: .Bd -literal -offset indent set openmode active .Ed .Pp This tells .Nm ppp to initiate LCP. Without this line, there's a possibility of both sides of the connection just sitting there and looking at eachother rather than communicating. .El Please refer to .Pa /etc/ppp/ppp.conf.sample and .Pa /etc/ppp/ppp.linkup.sample for some real examples. The pmdemand label should be appropriate for most ISPs. .Sh Logging facility .Nm is able to generate the following log info into .Pa /var/log/ppp.log : .Bl -column SMMMMMM -offset indent -compat .It Li Phase Phase transition log output .It Li Chat Generate Chat script trace log .It Li Connect Generate complete Chat log .It Li Carrier Log Chat lines with 'CARRIER' .It Li LQM Generate LQR report .It Li LCP Generate LCP/IPCP packet trace .It Li Link Log address assignments and link up/down events .It Li TCP/IP Dump TCP/IP packet .It Li HDLC Dump HDLC packet in hex .It Li Async Dump async level packet in hex .El The .Dq set debug command allows you to set logging output level, of which multiple levels can be specified. The default is equivalent to .Dq set debug carrier link phase . If a HUP signal is received, the log file is closed and re-opened to facilitate log file rotation. .Sh MORE DETAILS .Bl -bullet -compact .It Please read the Japanese doc for complete explanation. It may not be useful for non-japanese readers, but examples in the document may help you to guess. .It Please read example configuration files. .It Use .Dq help , .Dq show ? , .Dq set ? and .Dq set ? commands. .It NetBSD and BSDI-1.0 were supported in previous releases but are no longer supported in this release. Please contact the author if you need old driver code. .El .Sh FILES .Nm refers to three files: ppp.conf, ppp.linkup and ppp.secret. These files are placed in .Pa /etc/ppp , but the user can create his own files under his $HOME directory as .Pa .ppp.conf , .Pa .ppp.linkup and .Pa .ppp.secret. .Nm will always try to consult the user's personal setup first. .Bl -tag -width flag .Pa $HOME/ppp/.ppp.[conf|linkup|secret] User dependent configuration files. .Pa /etc/ppp/ppp.conf System default configuration file. .Pa /etc/ppp/ppp.secret An authorization file for each system. .Pa /etc/ppp/ppp.linkup A file to check when .Nm establishes a network level connection. .Pa /var/log/ppp.log Logging and debugging information file. .Pa /var/spool/lock/Lck..* tty port locking file. .Pa /var/run/PPP.system Holds the pid for ppp -auto system. .Pa /var/run/ppp.tun0.pid The process id (pid) of the ppp program connected to the ppp0 device. .Pa /etc/services Get port number if port number is using service name. .El .Sh SEE ALSO .Xr chat 8 , .Xr pppd 8 .Sh HISTORY This program was submitted in FreeBSD-2.0.5 Atsushi Murai (amurai@spec.co.jp). .Sh AUTHORS Toshiharu OHNO (tony-o@iij.ad.jp) diff --git a/usr.sbin/ppp/vars.c b/usr.sbin/ppp/vars.c index c976892b89a9..cbbad62cd5e6 100644 --- a/usr.sbin/ppp/vars.c +++ b/usr.sbin/ppp/vars.c @@ -1,207 +1,208 @@ /* * PPP configuration variables * * Written by Toshiharu OHNO (tony-o@iij.ad.jp) * * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the Internet Initiative Japan, Inc. The name of the * IIJ may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: vars.c,v 1.12 1997/02/22 16:11:00 peter Exp $ + * $Id: vars.c,v 1.13 1997/04/14 23:48:19 brian Exp $ * */ #include "fsm.h" #include "command.h" #include "hdlc.h" #include "termios.h" #include "vars.h" #include "auth.h" #include "defs.h" char VarVersion[] = "Version 0.94"; -char VarLocalVersion[] = "$Date: 1997/02/22 16:11:00 $"; +char VarLocalVersion[] = "$Date: 1997/04/14 23:48:19 $"; /* * Order of conf option is important. See vars.h. */ struct confdesc pppConfs[] = { { "vjcomp", CONF_ENABLE, CONF_ACCEPT }, { "lqr", CONF_ENABLE, CONF_ACCEPT }, { "chap", CONF_DISABLE, CONF_ACCEPT }, { "pap", CONF_DISABLE, CONF_ACCEPT }, { "acfcomp", CONF_ENABLE, CONF_ACCEPT }, { "protocomp", CONF_ENABLE, CONF_ACCEPT }, { "pred1", CONF_ENABLE, CONF_ACCEPT }, { "proxy", CONF_DISABLE, CONF_DENY }, { "msext", CONF_DISABLE, CONF_ACCEPT }, { "passwdauth",CONF_DISABLE, CONF_DENY }, { NULL }, }; struct pppvars pppVars = { DEF_MRU, 0, MODEM_SPEED, CS8, MODEM_CTSRTS, 180, 30, 3, - REDIAL_PERIOD, NEXT_REDIAL_PERIOD, 1, MODEM_DEV, OPEN_PASSIVE, LOCAL_NO_AUTH, + RECONNECT_TIMER, RECONNECT_TRIES, REDIAL_PERIOD, + NEXT_REDIAL_PERIOD, 1, MODEM_DEV, OPEN_PASSIVE, LOCAL_NO_AUTH, }; int DisplayCommand() { struct confdesc *vp; printf("Current configuration option settings..\n\n"); printf("Name\t\tMy Side\t\tHis Side\n"); printf("----------------------------------------\n"); for (vp = pppConfs; vp->name; vp++) printf("%-10s\t%s\t\t%s\n", vp->name, (vp->myside == CONF_ENABLE)? "enable" : "disable", (vp->hisside == CONF_ACCEPT)? "accept" : "deny"); return(1); } int DisableCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { struct confdesc *vp; int found = FALSE; if (argc < 1) { printf("disable what?\n"); return(1); } do { for (vp = pppConfs; vp->name; vp++) { if (strcasecmp(vp->name, *argv) == 0) { vp->myside = CONF_DISABLE; found = TRUE; } } if ( found == FALSE ) printf("%s - No such key word\n", *argv ); argc--; argv++; } while (argc > 0); return(1); } int EnableCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { struct confdesc *vp; int found = FALSE; if (argc < 1) { printf("enable what?\n"); return(1); } do { for (vp = pppConfs; vp->name; vp++) { if (strcasecmp(vp->name, *argv) == 0) { vp->myside = CONF_ENABLE; found = TRUE; } } if ( found == FALSE ) printf("%s - No such key word\n", *argv ); argc--; argv++; } while (argc > 0); return(1); } int AcceptCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { struct confdesc *vp; int found = FALSE; if (argc < 1) { printf("accept what?\n"); return(1); } do { for (vp = pppConfs; vp->name; vp++) { if (strcasecmp(vp->name, *argv) == 0) { vp->hisside = CONF_ACCEPT; found = TRUE; } } if ( found == FALSE ) printf("%s - No such key word\n", *argv ); argc--; argv++; } while (argc > 0); return(1); } int DenyCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { struct confdesc *vp; int found = FALSE; if (argc < 1) { printf("enable what?\n"); return(1); } do { for (vp = pppConfs; vp->name; vp++) { if (strcasecmp(vp->name, *argv) == 0) { vp->hisside = CONF_DENY; found = TRUE; } } if ( found == FALSE ) printf("%s - No such key word\n", *argv ); argc--; argv++; } while (argc > 0); return(1); } int LocalAuthCommand(list, argc, argv) struct cmdtab *list; int argc; char **argv; { if (argc < 1) { printf("Please Enter passwd for manipulating.\n"); return(1); } switch ( LocalAuthValidate( SECRETFILE, VarShortHost, *argv ) ) { case INVALID: pppVars.lauth = LOCAL_NO_AUTH; break; case VALID: pppVars.lauth = LOCAL_AUTH; break; case NOT_FOUND: pppVars.lauth = LOCAL_AUTH; printf("WARING: No Entry for this system\n"); break; default: pppVars.lauth = LOCAL_NO_AUTH; printf("Ooops?\n"); break; } return(1); } diff --git a/usr.sbin/ppp/vars.h b/usr.sbin/ppp/vars.h index 57c27b9cdb4f..06691de80ec8 100644 --- a/usr.sbin/ppp/vars.h +++ b/usr.sbin/ppp/vars.h @@ -1,114 +1,119 @@ /* * Written by Toshiharu OHNO (tony-o@iij.ad.jp) * * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the Internet Initiative Japan. The name of the * IIJ may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: vars.h,v 1.10 1997/02/22 16:11:02 peter Exp $ + * $Id: vars.h,v 1.11 1997/04/14 23:48:20 brian Exp $ * * TODO: */ #ifndef _VARS_H_ #define _VARS_H_ #include struct confdesc { char *name; int myside, hisside; }; #define CONF_DISABLE 0 #define CONF_ENABLE 1 #define CONF_DENY 0 #define CONF_ACCEPT 1 #define ConfVjcomp 0 #define ConfLqr 1 #define ConfChap 2 #define ConfPap 3 #define ConfAcfcomp 4 #define ConfProtocomp 5 #define ConfPred1 6 #define ConfProxy 7 #define ConfMSExt 8 #define ConfPasswdAuth 9 #define MAXCONFS 10 #define Enabled(x) (pppConfs[x].myside & CONF_ENABLE) #define Acceptable(x) (pppConfs[x].hisside & CONF_ACCEPT) extern struct confdesc pppConfs[MAXCONFS+1]; struct pppvars { u_long var_mru; /* Initial MRU value */ int var_accmap; /* Initial ACCMAP value */ int modem_speed; /* Current modem speed */ int modem_parity; /* Parity setting */ int modem_ctsrts; /* Use CTS/RTS on modem port? (boolean) */ int idle_timeout; /* Idle timeout value */ int lqr_timeout; /* LQR timeout value */ int retry_timeout; /* Retry timeout value */ + int reconnect_timer; /* Timeout before reconnect on carrier loss */ + int reconnect_tries; /* Attempt reconnect on carrier loss */ int redial_timeout; /* Redial timeout value */ int redial_next_timeout; /* Redial next timeout value */ int dial_tries; /* Dial attempts before giving up, 0 == forever */ char modem_dev[20]; /* Name of device */ int open_mode; /* LCP open mode */ #define LOCAL_AUTH 0x01 #define LOCAL_NO_AUTH 0x02 u_char lauth; /* Local Authorized status */ #define DIALUP_REQ 0x01 #define DIALUP_DONE 0x02 char dial_script[200]; /* Dial script */ char login_script[200]; /* Login script */ char auth_key[50]; /* PAP/CHAP key */ char auth_name[50]; /* PAP/CHAP system name */ char phone_numbers[200]; /* Telephone Numbers */ char phone_copy[200]; /* copy for strsep() */ char *next_phone; /* Next phone from the list */ char shostname[MAXHOSTNAMELEN];/* Local short Host Name */ }; #define VarAccmap pppVars.var_accmap #define VarMRU pppVars.var_mru #define VarDevice pppVars.modem_dev #define VarSpeed pppVars.modem_speed #define VarParity pppVars.modem_parity #define VarCtsRts pppVars.modem_ctsrts #define VarOpenMode pppVars.open_mode #define VarLocalAuth pppVars.lauth #define VarDialScript pppVars.dial_script #define VarLoginScript pppVars.login_script #define VarIdleTimeout pppVars.idle_timeout #define VarLqrTimeout pppVars.lqr_timeout #define VarRetryTimeout pppVars.retry_timeout #define VarAuthKey pppVars.auth_key #define VarAuthName pppVars.auth_name #define VarPhoneList pppVars.phone_numbers #define VarPhoneCopy pppVars.phone_copy #define VarNextPhone pppVars.next_phone #define VarShortHost pppVars.shostname +#define VarReconnectTimer pppVars.reconnect_timer +#define VarReconnectTries pppVars.reconnect_tries #define VarRedialTimeout pppVars.redial_timeout #define VarRedialNextTimeout pppVars.redial_next_timeout #define VarDialTries pppVars.dial_tries #define DEV_IS_SYNC (VarSpeed == 0) extern struct pppvars pppVars; int ipInOctets, ipOutOctets, ipKeepAlive; int ipConnectSecs, ipIdleSecs; +int lostCarrier; #endif