main.c revision 32860
16059Samurai/* 26059Samurai * User Process PPP 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 2032860Sbrian * $Id: main.c,v 1.120 1998/01/27 23:14:51 brian Exp $ 218857Srgrimes * 226059Samurai * TODO: 236059Samurai * o Add commands for traffic summary, version display, etc. 246059Samurai * o Add signal handler for misc controls. 256059Samurai */ 2630715Sbrian#include <sys/param.h> 2731195Sbrian#include <sys/time.h> 2831195Sbrian#include <sys/select.h> 2930715Sbrian#include <sys/socket.h> 3032663Sbrian#include <net/if.h> 3132663Sbrian#include <net/if_tun.h> 3230715Sbrian#include <netinet/in.h> 3330715Sbrian#include <netinet/in_systm.h> 3430715Sbrian#include <netinet/ip.h> 3530715Sbrian#include <arpa/inet.h> 3630715Sbrian 3730715Sbrian#include <errno.h> 386059Samurai#include <fcntl.h> 3911336Samurai#include <paths.h> 4030715Sbrian#include <signal.h> 4130715Sbrian#include <stdio.h> 4230715Sbrian#include <stdlib.h> 4330715Sbrian#include <string.h> 446059Samurai#include <sys/time.h> 4530715Sbrian#include <sys/wait.h> 466059Samurai#include <termios.h> 4718786Sjkh#include <unistd.h> 4830715Sbrian 4931343Sbrian#include "command.h" 5030715Sbrian#include "mbuf.h" 5130715Sbrian#include "log.h" 5230715Sbrian#include "defs.h" 5331061Sbrian#include "id.h" 5430715Sbrian#include "timer.h" 5530715Sbrian#include "fsm.h" 566059Samurai#include "modem.h" 576059Samurai#include "os.h" 586059Samurai#include "hdlc.h" 5931514Sbrian#include "lcp.h" 6013389Sphk#include "ccp.h" 616059Samurai#include "ipcp.h" 6226142Sbrian#include "loadalias.h" 636059Samurai#include "vars.h" 646735Samurai#include "auth.h" 657001Samurai#include "filter.h" 6613389Sphk#include "systems.h" 6713389Sphk#include "ip.h" 6823840Sbrian#include "sig.h" 6926940Sbrian#include "server.h" 7030715Sbrian#include "main.h" 7130715Sbrian#include "vjcomp.h" 7230715Sbrian#include "async.h" 7331158Sbrian#include "pathnames.h" 7431195Sbrian#include "tun.h" 7531343Sbrian#include "route.h" 766059Samurai 776735Samurai#ifndef O_NONBLOCK 786735Samurai#ifdef O_NDELAY 796735Samurai#define O_NONBLOCK O_NDELAY 806735Samurai#endif 816735Samurai#endif 826735Samurai 8330715Sbrianint TermMode = 0; 8430715Sbrianint tunno = 0; 856059Samurai 8628679Sbrianstatic struct termios oldtio; /* Original tty mode */ 8728679Sbrianstatic struct termios comtio; /* Command level tty mode */ 8820813Sjkhstatic pid_t BGPid = 0; 8925634Sbrianstatic char pid_filename[MAXPATHLEN]; 9027061Sbrianstatic int dial_up; 916059Samurai 9230715Sbrianstatic void DoLoop(void); 9330715Sbrianstatic void TerminalStop(int); 9431343Sbrianstatic const char *ex_desc(int); 9530715Sbrian 966059Samuraistatic void 9726858SbrianTtyInit(int DontWantInt) 986059Samurai{ 996059Samurai struct termios newtio; 1006059Samurai int stat; 1016059Samurai 10232129Sbrian stat = fcntl(netfd, F_GETFL, 0); 10325630Sbrian if (stat > 0) { 10428679Sbrian stat |= O_NONBLOCK; 10532129Sbrian (void) fcntl(netfd, F_SETFL, stat); 10625630Sbrian } 1076059Samurai newtio = oldtio; 10828679Sbrian newtio.c_lflag &= ~(ECHO | ISIG | ICANON); 1096059Samurai newtio.c_iflag = 0; 1106059Samurai newtio.c_oflag &= ~OPOST; 1116059Samurai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 11226858Sbrian if (DontWantInt) 11326858Sbrian newtio.c_cc[VINTR] = _POSIX_VDISABLE; 1146059Samurai newtio.c_cc[VMIN] = 1; 1156059Samurai newtio.c_cc[VTIME] = 0; 1166059Samurai newtio.c_cflag |= CS8; 11732129Sbrian tcsetattr(netfd, TCSANOW, &newtio); 1186059Samurai comtio = newtio; 1196059Samurai} 1206059Samurai 1216059Samurai/* 1226059Samurai * Set tty into command mode. We allow canonical input and echo processing. 1236059Samurai */ 12410528Samuraivoid 12528679SbrianTtyCommandMode(int prompt) 1266059Samurai{ 1276059Samurai struct termios newtio; 1286059Samurai int stat; 1296059Samurai 1306059Samurai if (!(mode & MODE_INTER)) 1316059Samurai return; 13232129Sbrian tcgetattr(netfd, &newtio); 13328679Sbrian newtio.c_lflag |= (ECHO | ISIG | ICANON); 1346059Samurai newtio.c_iflag = oldtio.c_iflag; 1356059Samurai newtio.c_oflag |= OPOST; 13632129Sbrian tcsetattr(netfd, TCSADRAIN, &newtio); 13732129Sbrian stat = fcntl(netfd, F_GETFL, 0); 13825630Sbrian if (stat > 0) { 13928679Sbrian stat |= O_NONBLOCK; 14032129Sbrian (void) fcntl(netfd, F_SETFL, stat); 14125630Sbrian } 1426059Samurai TermMode = 0; 14328679Sbrian if (prompt) 14428679Sbrian Prompt(); 1456059Samurai} 1466059Samurai 1476059Samurai/* 1486059Samurai * Set tty into terminal mode which is used while we invoke term command. 1496059Samurai */ 1506059Samuraivoid 1516059SamuraiTtyTermMode() 1526059Samurai{ 1536059Samurai int stat; 1546059Samurai 15532129Sbrian tcsetattr(netfd, TCSADRAIN, &comtio); 15632129Sbrian stat = fcntl(netfd, F_GETFL, 0); 15725630Sbrian if (stat > 0) { 15828679Sbrian stat &= ~O_NONBLOCK; 15932129Sbrian (void) fcntl(netfd, F_SETFL, stat); 16025630Sbrian } 1616059Samurai TermMode = 1; 1626059Samurai} 1636059Samurai 1646059Samuraivoid 16510528SamuraiTtyOldMode() 1666059Samurai{ 1676059Samurai int stat; 1686059Samurai 16932129Sbrian stat = fcntl(netfd, F_GETFL, 0); 17025630Sbrian if (stat > 0) { 17128679Sbrian stat &= ~O_NONBLOCK; 17232129Sbrian (void) fcntl(netfd, F_SETFL, stat); 17325630Sbrian } 17432129Sbrian tcsetattr(netfd, TCSADRAIN, &oldtio); 17510528Samurai} 17610528Samurai 17710528Samuraivoid 17828679SbrianCleanup(int excode) 17910528Samurai{ 18032021Sbrian DropClient(1); 18131081Sbrian ServerClose(); 18230825Sbrian OsInterfaceDown(1); 18330825Sbrian HangupModem(1); 18430697Sbrian nointr_sleep(1); 18531121Sbrian DeleteIfRoutes(1); 18631061Sbrian ID0unlink(pid_filename); 18723863Sbrian if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 18823863Sbrian char c = EX_ERRDEAD; 18928679Sbrian 19028679Sbrian if (write(BGFiledes[1], &c, 1) == 1) 19128679Sbrian LogPrintf(LogPHASE, "Parent notified of failure.\n"); 19223863Sbrian else 19328679Sbrian LogPrintf(LogPHASE, "Failed to notify parent of failure.\n"); 19423863Sbrian close(BGFiledes[1]); 19523863Sbrian } 19628679Sbrian LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 19710528Samurai TtyOldMode(); 19831061Sbrian LogClose(); 1996059Samurai 2006059Samurai exit(excode); 2016059Samurai} 2026059Samurai 2036059Samuraistatic void 20428679SbrianCloseConnection(int signo) 2056059Samurai{ 20626858Sbrian /* NOTE, these are manual, we've done a setsid() */ 20731121Sbrian pending_signal(SIGINT, SIG_IGN); 20827157Sbrian LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo); 20928679Sbrian reconnectState = RECON_FALSE; 21028684Sbrian reconnectCount = 0; 21128684Sbrian DownConnection(); 21230715Sbrian dial_up = 0; 21331121Sbrian pending_signal(SIGINT, CloseConnection); 2146059Samurai} 2156059Samurai 2166059Samuraistatic void 21728679SbrianCloseSession(int signo) 2186059Samurai{ 21928679Sbrian if (BGPid) { 22028679Sbrian kill(BGPid, SIGINT); 22128679Sbrian exit(EX_TERM); 22228679Sbrian } 22328679Sbrian LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo); 22428679Sbrian reconnect(RECON_FALSE); 22528679Sbrian LcpClose(); 22628679Sbrian Cleanup(EX_TERM); 2276059Samurai} 2286059Samurai 22910528Samuraistatic void 23031343SbrianTerminalCont(int signo) 23110528Samurai{ 23223840Sbrian pending_signal(SIGCONT, SIG_DFL); 23323840Sbrian pending_signal(SIGTSTP, TerminalStop); 23432129Sbrian TtyCommandMode(getpgrp() == tcgetpgrp(netfd)); 23510528Samurai} 23610528Samurai 23710528Samuraistatic void 23828679SbrianTerminalStop(int signo) 23910528Samurai{ 24023840Sbrian pending_signal(SIGCONT, TerminalCont); 24110528Samurai TtyOldMode(); 24223840Sbrian pending_signal(SIGTSTP, SIG_DFL); 24310528Samurai kill(getpid(), signo); 24410528Samurai} 24510528Samurai 24626940Sbrianstatic void 24728679SbrianSetUpServer(int signo) 24826940Sbrian{ 24926940Sbrian int res; 25028679Sbrian 25131081Sbrian VarHaveLocalAuthKey = 0; 25231081Sbrian LocalAuthInit(); 25328679Sbrian if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0) 25429083Sbrian LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n", 25529083Sbrian res, SERVER_PORT + tunno); 25626940Sbrian} 25726940Sbrian 25831081Sbrianstatic void 25931081SbrianBringDownServer(int signo) 26031081Sbrian{ 26131081Sbrian VarHaveLocalAuthKey = 0; 26231081Sbrian LocalAuthInit(); 26331081Sbrian ServerClose(); 26431081Sbrian} 26531081Sbrian 26631343Sbrianstatic const char * 26725908Sbrianex_desc(int ex) 26825908Sbrian{ 26925908Sbrian static char num[12]; 27031343Sbrian static const char *desc[] = { 27131343Sbrian "normal", "start", "sock", "modem", "dial", "dead", "done", 27231343Sbrian "reboot", "errdead", "hangup", "term", "nodial", "nologin" 27331343Sbrian }; 27410528Samurai 27531962Sbrian if (ex >= 0 && ex < sizeof desc / sizeof *desc) 27625908Sbrian return desc[ex]; 27725908Sbrian snprintf(num, sizeof num, "%d", ex); 27825908Sbrian return num; 27925908Sbrian} 28025908Sbrian 28130715Sbrianstatic void 28231343SbrianUsage(void) 2836059Samurai{ 28420120Snate fprintf(stderr, 28531343Sbrian "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]" 28631343Sbrian#ifndef NOALIAS 28731343Sbrian " [ -alias ]" 28831343Sbrian#endif 28931343Sbrian " [system]\n"); 2906059Samurai exit(EX_START); 2916059Samurai} 2926059Samurai 29331197Sbrianstatic char * 2946059SamuraiProcessArgs(int argc, char **argv) 2956059Samurai{ 2966059Samurai int optc; 2976059Samurai char *cp; 2986059Samurai 2996059Samurai optc = 0; 30031121Sbrian mode = MODE_INTER; 3016059Samurai while (argc > 0 && **argv == '-') { 3026059Samurai cp = *argv + 1; 30331121Sbrian if (strcmp(cp, "auto") == 0) { 3046059Samurai mode |= MODE_AUTO; 30531121Sbrian mode &= ~MODE_INTER; 30631121Sbrian } else if (strcmp(cp, "background") == 0) { 30731121Sbrian mode |= MODE_BACKGROUND; 30831121Sbrian mode &= ~MODE_INTER; 30931121Sbrian } else if (strcmp(cp, "direct") == 0) { 3106059Samurai mode |= MODE_DIRECT; 31131121Sbrian mode &= ~MODE_INTER; 31231121Sbrian } else if (strcmp(cp, "dedicated") == 0) { 3136059Samurai mode |= MODE_DEDICATED; 31431121Sbrian mode &= ~MODE_INTER; 31531121Sbrian } else if (strcmp(cp, "ddial") == 0) { 31631121Sbrian mode |= MODE_DDIAL; 31731121Sbrian mode &= ~MODE_INTER; 31831343Sbrian#ifndef NOALIAS 31931121Sbrian } else if (strcmp(cp, "alias") == 0) { 32026142Sbrian if (loadAliasHandlers(&VarAliasHandlers) == 0) 32128679Sbrian mode |= MODE_ALIAS; 32226142Sbrian else 32328679Sbrian LogPrintf(LogWARN, "Cannot load alias library\n"); 32428679Sbrian optc--; /* this option isn't exclusive */ 32531343Sbrian#endif 32628679Sbrian } else 3276059Samurai Usage(); 3286059Samurai optc++; 32928679Sbrian argv++; 33028679Sbrian argc--; 3316059Samurai } 3326059Samurai if (argc > 1) { 3336059Samurai fprintf(stderr, "specify only one system label.\n"); 3346059Samurai exit(EX_START); 3356059Samurai } 3366059Samurai 3376059Samurai if (optc > 1) { 3386059Samurai fprintf(stderr, "specify only one mode.\n"); 3396059Samurai exit(EX_START); 3406059Samurai } 34131197Sbrian 34231197Sbrian return argc == 1 ? *argv : NULL; /* Don't SetLabel yet ! */ 3436059Samurai} 3446059Samurai 34526940Sbrianint 34628679Sbrianmain(int argc, char **argv) 3476059Samurai{ 34825707Sbrian FILE *lockfile; 34931197Sbrian char *name, *label; 35031823Sbrian int nfds; 35126516Sbrian 35231823Sbrian nfds = getdtablesize(); 35331823Sbrian if (nfds >= FD_SETSIZE) 35431823Sbrian /* 35531823Sbrian * If we've got loads of file descriptors, make sure they're all 35631823Sbrian * closed. If they aren't, we may end up with a seg fault when our 35731823Sbrian * `fd_set's get too big when select()ing ! 35831823Sbrian */ 35931823Sbrian while (--nfds > 2) 36031823Sbrian close(nfds); 36131823Sbrian 36226551Sbrian VarTerm = 0; 36330715Sbrian name = strrchr(argv[0], '/'); 36428679Sbrian LogOpen(name ? name + 1 : argv[0]); 36526516Sbrian 36632129Sbrian tcgetattr(STDIN_FILENO, &oldtio); /* Save original tty mode */ 36732129Sbrian 36828679Sbrian argc--; 36928679Sbrian argv++; 37031197Sbrian label = ProcessArgs(argc, argv); 37131121Sbrian if (!(mode & MODE_DIRECT)) 37226551Sbrian VarTerm = stdout; 37331121Sbrian 37431121Sbrian ID0init(); 37531158Sbrian if (ID0realuid() != 0) { 37631158Sbrian char conf[200], *ptr; 37731158Sbrian 37831158Sbrian snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 37931158Sbrian do { 38031158Sbrian if (!access(conf, W_OK)) { 38131158Sbrian LogPrintf(LogALERT, "ppp: Access violation: Please protect %s\n", conf); 38231158Sbrian return -1; 38331158Sbrian } 38431158Sbrian ptr = conf + strlen(conf)-2; 38531158Sbrian while (ptr > conf && *ptr != '/') 38631158Sbrian *ptr-- = '\0'; 38731158Sbrian } while (ptr >= conf); 38831158Sbrian } 38931158Sbrian 39031197Sbrian if (!ValidSystem(label)) { 39131121Sbrian fprintf(stderr, "You may not use ppp in this mode with this label\n"); 39231157Sbrian if (mode & MODE_DIRECT) { 39331157Sbrian const char *l; 39431197Sbrian l = label ? label : "default"; 39531157Sbrian LogPrintf(LogWARN, "Label %s rejected -direct connection\n", l); 39631157Sbrian } 39731157Sbrian LogClose(); 39831121Sbrian return 1; 39929083Sbrian } 40031121Sbrian 40131196Sbrian if (!GetShortHost()) 40231196Sbrian return 1; 40332833Sbrian IsInteractive(1); 4046059Samurai IpcpDefAddress(); 4056059Samurai 40631285Sbrian if (mode & MODE_INTER) 40731285Sbrian VarLocalAuth = LOCAL_AUTH; 40831285Sbrian 40926516Sbrian if (SelectSystem("default", CONFFILE) < 0 && VarTerm) 41026516Sbrian fprintf(VarTerm, "Warning: No default entry is given in config file.\n"); 4116059Samurai 4126059Samurai if (OpenTunnel(&tunno) < 0) { 41331690Sbrian LogPrintf(LogWARN, "OpenTunnel: %s\n", strerror(errno)); 41426940Sbrian return EX_START; 4156059Samurai } 41632351Sbrian CleanInterface(IfDevName); 41732833Sbrian if ((mode & MODE_OUTGOING_DAEMON) && !(mode & MODE_DEDICATED)) 41831197Sbrian if (label == NULL) { 41926516Sbrian if (VarTerm) 42028679Sbrian fprintf(VarTerm, "Destination system must be specified in" 42128679Sbrian " auto, background or ddial mode.\n"); 42226940Sbrian return EX_START; 4236059Samurai } 42431121Sbrian 42527157Sbrian pending_signal(SIGHUP, CloseSession); 42623840Sbrian pending_signal(SIGTERM, CloseSession); 42727157Sbrian pending_signal(SIGINT, CloseConnection); 42823840Sbrian pending_signal(SIGQUIT, CloseSession); 4296735Samurai#ifdef SIGPIPE 43024753Sache signal(SIGPIPE, SIG_IGN); 4316735Samurai#endif 4326735Samurai#ifdef SIGALRM 43323840Sbrian pending_signal(SIGALRM, SIG_IGN); 4346735Samurai#endif 43528679Sbrian if (mode & MODE_INTER) { 43610528Samurai#ifdef SIGTSTP 43726940Sbrian pending_signal(SIGTSTP, TerminalStop); 43810528Samurai#endif 43910528Samurai#ifdef SIGTTIN 44026940Sbrian pending_signal(SIGTTIN, TerminalStop); 44110528Samurai#endif 44210528Samurai#ifdef SIGTTOU 44326940Sbrian pending_signal(SIGTTOU, SIG_IGN); 44410528Samurai#endif 44526940Sbrian } 44631121Sbrian if (!(mode & MODE_INTER)) { 44726940Sbrian#ifdef SIGUSR1 44826940Sbrian pending_signal(SIGUSR1, SetUpServer); 44926940Sbrian#endif 45031081Sbrian#ifdef SIGUSR2 45131081Sbrian pending_signal(SIGUSR2, BringDownServer); 45231081Sbrian#endif 45331121Sbrian } 4546059Samurai 45531197Sbrian if (label) { 45631197Sbrian if (SelectSystem(label, CONFFILE) < 0) { 45731154Sbrian LogPrintf(LogWARN, "Destination system %s not found in conf file.\n", 45831154Sbrian GetLabel()); 4596059Samurai Cleanup(EX_START); 4606059Samurai } 46131197Sbrian /* 46231197Sbrian * We don't SetLabel() 'till now in case SelectSystem() has an 46331197Sbrian * embeded load "otherlabel" command. 46431197Sbrian */ 46531197Sbrian SetLabel(label); 46631121Sbrian if (mode & MODE_OUTGOING_DAEMON && 46731121Sbrian DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 46831154Sbrian LogPrintf(LogWARN, "You must \"set ifaddr\" in label %s for" 46931197Sbrian " auto, background or ddial mode.\n", label); 4706059Samurai Cleanup(EX_START); 4716059Samurai } 4726059Samurai } 47326940Sbrian 47431121Sbrian if (mode & MODE_DAEMON) { 47520813Sjkh if (mode & MODE_BACKGROUND) { 47628679Sbrian if (pipe(BGFiledes)) { 47728974Sbrian LogPrintf(LogERROR, "pipe: %s\n", strerror(errno)); 47820813Sjkh Cleanup(EX_SOCK); 47920813Sjkh } 4806059Samurai } 4816059Samurai 4826059Samurai if (!(mode & MODE_DIRECT)) { 48320813Sjkh pid_t bgpid; 48411336Samurai 48528679Sbrian bgpid = fork(); 48620813Sjkh if (bgpid == -1) { 48728974Sbrian LogPrintf(LogERROR, "fork: %s\n", strerror(errno)); 48828679Sbrian Cleanup(EX_SOCK); 48920813Sjkh } 49020813Sjkh if (bgpid) { 49120813Sjkh char c = EX_NORMAL; 49211336Samurai 49320813Sjkh if (mode & MODE_BACKGROUND) { 49420813Sjkh /* Wait for our child to close its pipe before we exit. */ 49520813Sjkh BGPid = bgpid; 49628679Sbrian close(BGFiledes[1]); 49725908Sbrian if (read(BGFiledes[0], &c, 1) != 1) { 49826516Sbrian fprintf(VarTerm, "Child exit, no status.\n"); 49928679Sbrian LogPrintf(LogPHASE, "Parent: Child exit, no status.\n"); 50025908Sbrian } else if (c == EX_NORMAL) { 50126516Sbrian fprintf(VarTerm, "PPP enabled.\n"); 50228679Sbrian LogPrintf(LogPHASE, "Parent: PPP enabled.\n"); 50325908Sbrian } else { 50428679Sbrian fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c)); 50526516Sbrian LogPrintf(LogPHASE, "Parent: Child failed (%s).\n", 50628679Sbrian ex_desc((int) c)); 50728679Sbrian } 50828679Sbrian close(BGFiledes[0]); 50920813Sjkh } 51028679Sbrian return c; 51123863Sbrian } else if (mode & MODE_BACKGROUND) 51228679Sbrian close(BGFiledes[0]); 51325707Sbrian } 51420813Sjkh 51528679Sbrian VarTerm = 0; /* We know it's currently stdout */ 51632129Sbrian close(STDOUT_FILENO); 51732129Sbrian close(STDERR_FILENO); 51826551Sbrian 51926686Sbrian if (mode & MODE_DIRECT) 52032129Sbrian /* STDIN_FILENO gets used by OpenModem in DIRECT mode */ 52126858Sbrian TtyInit(1); 52231121Sbrian else if (mode & MODE_DAEMON) { 52326686Sbrian setsid(); 52432129Sbrian close(STDIN_FILENO); 52526686Sbrian } 5266059Samurai } else { 52732129Sbrian close(STDIN_FILENO); 52832129Sbrian if ((netfd = open(_PATH_TTY, O_RDONLY)) < 0) { 52932129Sbrian fprintf(stderr, "Cannot open %s for intput !\n", _PATH_TTY); 53032129Sbrian return 2; 53132129Sbrian } 53232129Sbrian close(STDERR_FILENO); 53326858Sbrian TtyInit(0); 53410528Samurai TtyCommandMode(1); 5356059Samurai } 53629696Sbrian 53731962Sbrian snprintf(pid_filename, sizeof pid_filename, "%stun%d.pid", 53829696Sbrian _PATH_VARRUN, tunno); 53931061Sbrian lockfile = ID0fopen(pid_filename, "w"); 54031061Sbrian if (lockfile != NULL) { 54129696Sbrian fprintf(lockfile, "%d\n", (int) getpid()); 54229696Sbrian fclose(lockfile); 54332860Sbrian } 54432860Sbrian#ifndef RELEASE_CRUNCH 54532860Sbrian else 54629696Sbrian LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", 54729696Sbrian pid_filename, strerror(errno)); 54832860Sbrian#endif 54929696Sbrian 55026516Sbrian LogPrintf(LogPHASE, "PPP Started.\n"); 5516059Samurai 5526059Samurai 5536059Samurai do 55428679Sbrian DoLoop(); 5556059Samurai while (mode & MODE_DEDICATED); 5566059Samurai 5576059Samurai Cleanup(EX_DONE); 55826940Sbrian return 0; 5596059Samurai} 5606059Samurai 5616059Samurai/* 56220813Sjkh * Turn into packet mode, where we speak PPP. 5636059Samurai */ 5646059Samuraivoid 56532658SbrianPacketMode(int delay) 5666059Samurai{ 56731034Sbrian if (RawModem() < 0) { 56826516Sbrian LogPrintf(LogWARN, "PacketMode: Not connected.\n"); 5696059Samurai return; 5706059Samurai } 5716059Samurai AsyncInit(); 57230187Sbrian VjInit(15); 5736059Samurai LcpInit(); 5746059Samurai IpcpInit(); 5756059Samurai CcpInit(); 5766059Samurai LcpUp(); 5776059Samurai 57832658Sbrian LcpOpen(delay); 57931121Sbrian if (mode & MODE_INTER) 58010528Samurai TtyCommandMode(1); 58131121Sbrian if (VarTerm) { 58231121Sbrian fprintf(VarTerm, "Packet mode.\n"); 58331121Sbrian aft_cmd = 1; 5846059Samurai } 5856059Samurai} 5866059Samurai 5876059Samuraistatic void 58831343SbrianShowHelp(void) 5896059Samurai{ 59026901Sbrian fprintf(stderr, "The following commands are available:\r\n"); 59126901Sbrian fprintf(stderr, " ~p\tEnter Packet mode\r\n"); 59226901Sbrian fprintf(stderr, " ~-\tDecrease log level\r\n"); 59326901Sbrian fprintf(stderr, " ~+\tIncrease log level\r\n"); 59426901Sbrian fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n"); 59526901Sbrian fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n"); 59626901Sbrian fprintf(stderr, " ~.\tTerminate program\r\n"); 59726901Sbrian fprintf(stderr, " ~?\tThis help\r\n"); 5986059Samurai} 5996059Samurai 6006059Samuraistatic void 60131343SbrianReadTty(void) 6026059Samurai{ 6036059Samurai int n; 6046059Samurai char ch; 6056059Samurai static int ttystate; 60631070Sbrian char linebuff[LINE_LEN]; 60728679Sbrian 60826516Sbrian LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n", 60928679Sbrian TermMode, netfd, mode); 6106059Samurai if (!TermMode) { 61131962Sbrian n = read(netfd, linebuff, sizeof linebuff - 1); 6126735Samurai if (n > 0) { 61326516Sbrian aft_cmd = 1; 61430913Sbrian if (linebuff[n-1] == '\n') 61530913Sbrian linebuff[--n] = '\0'; 61631962Sbrian else 61731962Sbrian linebuff[n] = '\0'; 61831156Sbrian if (n) 61931156Sbrian DecodeCommand(linebuff, n, IsInteractive(0) ? NULL : "Client"); 62031156Sbrian Prompt(); 62132021Sbrian } else if (n <= 0) { 62232021Sbrian LogPrintf(LogPHASE, "Client connection closed.\n"); 62332021Sbrian DropClient(0); 62432021Sbrian } 6256059Samurai return; 6266059Samurai } 6276059Samurai 6286059Samurai /* 62928679Sbrian * We are in terminal mode, decode special sequences 6306059Samurai */ 63132129Sbrian n = read(netfd, &ch, 1); 63228974Sbrian LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n); 6336059Samurai 6346059Samurai if (n > 0) { 6356059Samurai switch (ttystate) { 6366059Samurai case 0: 6376059Samurai if (ch == '~') 6386059Samurai ttystate++; 6396059Samurai else 6406059Samurai write(modem, &ch, n); 6416059Samurai break; 6426059Samurai case 1: 6436059Samurai switch (ch) { 6446059Samurai case '?': 6456059Samurai ShowHelp(); 6466059Samurai break; 6476059Samurai case 'p': 64828679Sbrian 6496059Samurai /* 6506059Samurai * XXX: Should check carrier. 6516059Samurai */ 65232658Sbrian if (LcpFsm.state <= ST_CLOSED) 65332658Sbrian PacketMode(0); 6546059Samurai break; 6556059Samurai case '.': 6566059Samurai TermMode = 1; 65726516Sbrian aft_cmd = 1; 65810528Samurai TtyCommandMode(1); 6596059Samurai break; 66026516Sbrian case 't': 66126516Sbrian if (LogIsKept(LogDEBUG)) { 66226516Sbrian ShowTimers(); 66326516Sbrian break; 66426516Sbrian } 66526516Sbrian case 'm': 66626516Sbrian if (LogIsKept(LogDEBUG)) { 66731343Sbrian ShowMemMap(NULL); 66826516Sbrian break; 66926516Sbrian } 6706059Samurai default: 6716059Samurai if (write(modem, &ch, n) < 0) 67226516Sbrian LogPrintf(LogERROR, "error writing to modem.\n"); 6736059Samurai break; 6746059Samurai } 6756059Samurai ttystate = 0; 6766059Samurai break; 6776059Samurai } 6786059Samurai } 6796059Samurai} 6806059Samurai 6816059Samurai 6826059Samurai/* 6836059Samurai * Here, we'll try to detect HDLC frame 6846059Samurai */ 6856059Samurai 68631343Sbrianstatic const char *FrameHeaders[] = { 6876735Samurai "\176\377\003\300\041", 6886735Samurai "\176\377\175\043\300\041", 6896735Samurai "\176\177\175\043\100\041", 6906735Samurai "\176\175\337\175\043\300\041", 6916735Samurai "\176\175\137\175\043\100\041", 6926059Samurai NULL, 6936059Samurai}; 6946059Samurai 69531343Sbrianstatic const u_char * 69628679SbrianHdlcDetect(u_char * cp, int n) 6976059Samurai{ 69831343Sbrian const char *ptr, *fp, **hp; 6996059Samurai 70028679Sbrian cp[n] = '\0'; /* be sure to null terminated */ 7016059Samurai ptr = NULL; 7026059Samurai for (hp = FrameHeaders; *hp; hp++) { 7036735Samurai fp = *hp; 7046735Samurai if (DEV_IS_SYNC) 7056735Samurai fp++; 70628679Sbrian ptr = strstr((char *) cp, fp); 70713389Sphk if (ptr) 7086059Samurai break; 7096059Samurai } 71031343Sbrian return ((const u_char *) ptr); 7116059Samurai} 7126059Samurai 7136059Samuraistatic struct pppTimer RedialTimer; 7146059Samurai 7156059Samuraistatic void 71631343SbrianRedialTimeout(void *v) 7176059Samurai{ 7186059Samurai StopTimer(&RedialTimer); 71926516Sbrian LogPrintf(LogPHASE, "Redialing timer expired.\n"); 7206059Samurai} 7216059Samurai 7226059Samuraistatic void 72328679SbrianStartRedialTimer(int Timeout) 7246059Samurai{ 7256059Samurai StopTimer(&RedialTimer); 72611336Samurai 72724939Sbrian if (Timeout) { 72811336Samurai RedialTimer.state = TIMER_STOPPED; 72911336Samurai 73024939Sbrian if (Timeout > 0) 73128679Sbrian RedialTimer.load = Timeout * SECTICKS; 73211336Samurai else 73328679Sbrian RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 73411336Samurai 73526516Sbrian LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n", 73624939Sbrian RedialTimer.load / SECTICKS); 73724939Sbrian 73811336Samurai RedialTimer.func = RedialTimeout; 73911336Samurai StartTimer(&RedialTimer); 74011336Samurai } 7416059Samurai} 7426059Samurai 74331825Sbrian#define IN_SIZE sizeof(struct sockaddr_in) 74431825Sbrian#define UN_SIZE sizeof(struct sockaddr_in) 74531825Sbrian#define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 7466059Samurai 7476059Samuraistatic void 74831343SbrianDoLoop(void) 7496059Samurai{ 7506059Samurai fd_set rfds, wfds, efds; 75123598Sache int pri, i, n, wfd, nfds; 75231825Sbrian char hisaddr[ADDRSZ]; 75331825Sbrian struct sockaddr *sa = (struct sockaddr *)hisaddr; 75431825Sbrian struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr; 7556059Samurai struct timeval timeout, *tp; 75631825Sbrian int ssize = ADDRSZ; 75731343Sbrian const u_char *cp; 75811336Samurai int tries; 7599448Samurai int qlen; 76026858Sbrian int res; 76131195Sbrian struct tun_data tun; 76231195Sbrian#define rbuff tun.data 7636059Samurai 76425908Sbrian if (mode & MODE_DIRECT) { 76526551Sbrian LogPrintf(LogDEBUG, "Opening modem\n"); 76631034Sbrian if (OpenModem() < 0) 76729521Sbrian return; 76826516Sbrian LogPrintf(LogPHASE, "Packet mode enabled\n"); 76932658Sbrian PacketMode(VarOpenMode); 7706059Samurai } else if (mode & MODE_DEDICATED) { 77123598Sache if (modem < 0) 77231034Sbrian while (OpenModem() < 0) 77330697Sbrian nointr_sleep(VarReconnectTimer); 7746059Samurai } 77526516Sbrian fflush(VarTerm); 7766059Samurai 7777001Samurai timeout.tv_sec = 0; 7786059Samurai timeout.tv_usec = 0; 77926098Sbrian reconnectState = RECON_UNKNOWN; 7806059Samurai 78123863Sbrian if (mode & MODE_BACKGROUND) 78230715Sbrian dial_up = 1; /* Bring the line up */ 78323863Sbrian else 78430715Sbrian dial_up = 0; /* XXXX */ 78511336Samurai tries = 0; 7866059Samurai for (;;) { 78723598Sache nfds = 0; 78828679Sbrian FD_ZERO(&rfds); 78928679Sbrian FD_ZERO(&wfds); 79028679Sbrian FD_ZERO(&efds); 7917001Samurai 79228679Sbrian /* 79328679Sbrian * If the link is down and we're in DDIAL mode, bring it back up. 79420120Snate */ 79520120Snate if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 79630715Sbrian dial_up = 1; 79720120Snate 79825067Sbrian /* 79928679Sbrian * If we lost carrier and want to re-establish the connection due to the 80028679Sbrian * "set reconnect" value, we'd better bring the line back up. 80125067Sbrian */ 80225908Sbrian if (LcpFsm.state <= ST_CLOSED) { 80330715Sbrian if (!dial_up && reconnectState == RECON_TRUE) { 80428679Sbrian if (++reconnectCount <= VarReconnectTries) { 80528679Sbrian LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n", 80628679Sbrian reconnectCount, VarReconnectTries); 80725908Sbrian StartRedialTimer(VarReconnectTimer); 80830715Sbrian dial_up = 1; 80928679Sbrian } else { 81028679Sbrian if (VarReconnectTries) 81128679Sbrian LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n", 81228679Sbrian VarReconnectTries); 81328679Sbrian reconnectCount = 0; 81428679Sbrian if (mode & MODE_BACKGROUND) 81528679Sbrian Cleanup(EX_DEAD); 81628679Sbrian } 81728679Sbrian reconnectState = RECON_ENVOKED; 81831121Sbrian } else if (mode & MODE_DEDICATED) 81932658Sbrian PacketMode(VarOpenMode); 82025908Sbrian } 82125067Sbrian 82228679Sbrian /* 82328679Sbrian * If Ip packet for output is enqueued and require dial up, Just do it! 82428679Sbrian */ 82528679Sbrian if (dial_up && RedialTimer.state != TIMER_RUNNING) { 82626516Sbrian LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem); 82731034Sbrian if (OpenModem() < 0) { 82828679Sbrian tries++; 82928679Sbrian if (!(mode & MODE_DDIAL) && VarDialTries) 83028679Sbrian LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n", 83128679Sbrian tries, VarDialTries); 83228679Sbrian else 83328679Sbrian LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries); 83426551Sbrian 83526696Sbrian if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) { 83626551Sbrian if (mode & MODE_BACKGROUND) 83728679Sbrian Cleanup(EX_DIAL); /* Can't get the modem */ 83830715Sbrian dial_up = 0; 83928679Sbrian reconnectState = RECON_UNKNOWN; 84028679Sbrian reconnectCount = 0; 84126551Sbrian tries = 0; 84228679Sbrian } else 84326551Sbrian StartRedialTimer(VarRedialTimeout); 84411336Samurai } else { 84528679Sbrian tries++; /* Tries are per number, not per list of 84628679Sbrian * numbers. */ 84728679Sbrian if (!(mode & MODE_DDIAL) && VarDialTries) 84826696Sbrian LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries); 84928679Sbrian else 85028679Sbrian LogPrintf(LogCHAT, "Dial attempt %u\n", tries); 85126696Sbrian 85226858Sbrian if ((res = DialModem()) == EX_DONE) { 85331343Sbrian ModemTimeout(NULL); 85432658Sbrian PacketMode(VarOpenMode); 85530715Sbrian dial_up = 0; 85628679Sbrian reconnectState = RECON_UNKNOWN; 85711336Samurai tries = 0; 85811336Samurai } else { 85924844Sbrian if (mode & MODE_BACKGROUND) { 86026858Sbrian if (VarNextPhone == NULL || res == EX_SIG) 86128679Sbrian Cleanup(EX_DIAL); /* Tried all numbers - no luck */ 86224844Sbrian else 86324939Sbrian /* Try all numbers in background mode */ 86424939Sbrian StartRedialTimer(VarRedialNextTimeout); 86526858Sbrian } else if (!(mode & MODE_DDIAL) && 86628679Sbrian ((VarDialTries && tries >= VarDialTries) || 86728679Sbrian res == EX_SIG)) { 86824843Sbrian /* I give up ! Can't get through :( */ 86924939Sbrian StartRedialTimer(VarRedialTimeout); 87030715Sbrian dial_up = 0; 87128679Sbrian reconnectState = RECON_UNKNOWN; 87228679Sbrian reconnectCount = 0; 87324843Sbrian tries = 0; 87424843Sbrian } else if (VarNextPhone == NULL) 87524843Sbrian /* Dial failed. Keep quite during redial wait period. */ 87624939Sbrian StartRedialTimer(VarRedialTimeout); 87724843Sbrian else 87824939Sbrian StartRedialTimer(VarRedialNextTimeout); 87911336Samurai } 88011336Samurai } 8817001Samurai } 8829448Samurai qlen = ModemQlen(); 88313733Sdfr 88413733Sdfr if (qlen == 0) { 88513733Sdfr IpStartOutput(); 88613733Sdfr qlen = ModemQlen(); 88713733Sdfr } 88823598Sache if (modem >= 0) { 88923598Sache if (modem + 1 > nfds) 89023598Sache nfds = modem + 1; 8917001Samurai FD_SET(modem, &rfds); 8927001Samurai FD_SET(modem, &efds); 8939448Samurai if (qlen > 0) { 8947001Samurai FD_SET(modem, &wfds); 8957001Samurai } 8967001Samurai } 89723598Sache if (server >= 0) { 89823598Sache if (server + 1 > nfds) 89923598Sache nfds = server + 1; 90023598Sache FD_SET(server, &rfds); 90123598Sache } 9026059Samurai 90332063Sbrian#ifndef SIGALRM 90428679Sbrian /* 90528679Sbrian * *** IMPORTANT *** 90628679Sbrian * CPU is serviced every TICKUNIT micro seconds. This value must be chosen 90732063Sbrian * with great care. If this values is too big, it results in loss of 90832063Sbrian * characters from the modem and poor response. If this value is too 90932063Sbrian * small, ppp eats too much CPU time. 9106059Samurai */ 91132063Sbrian usleep(TICKUNIT); 9126059Samurai TimerService(); 91323840Sbrian#else 91423840Sbrian handle_signals(); 9156735Samurai#endif 91610877Sbde 91710877Sbde /* If there are aren't many packets queued, look for some more. */ 91823598Sache if (qlen < 20 && tun_in >= 0) { 91923598Sache if (tun_in + 1 > nfds) 92023598Sache nfds = tun_in + 1; 92110877Sbde FD_SET(tun_in, &rfds); 92223598Sache } 92323598Sache if (netfd >= 0) { 92423598Sache if (netfd + 1 > nfds) 92523598Sache nfds = netfd + 1; 9266059Samurai FD_SET(netfd, &rfds); 9276059Samurai FD_SET(netfd, &efds); 9286059Samurai } 92928679Sbrian#ifndef SIGALRM 9307001Samurai 9316059Samurai /* 93228679Sbrian * Normally, select() will not block because modem is writable. In AUTO 93328679Sbrian * mode, select will block until we find packet from tun 9346059Samurai */ 93528679Sbrian tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL; 93623598Sache i = select(nfds, &rfds, &wfds, &efds, tp); 9376735Samurai#else 93828679Sbrian 9398857Srgrimes /* 94028679Sbrian * When SIGALRM timer is running, a select function will be return -1 and 94128679Sbrian * EINTR after a Time Service signal hundler is done. If the redial 94228679Sbrian * timer is not running and we are trying to dial, poll with a 0 value 94328679Sbrian * timer. 9447001Samurai */ 94511336Samurai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 94623598Sache i = select(nfds, &rfds, &wfds, &efds, tp); 9476735Samurai#endif 94822074Sbrian 94928679Sbrian if (i == 0) { 95028679Sbrian continue; 9516059Samurai } 95228679Sbrian if (i < 0) { 95328679Sbrian if (errno == EINTR) { 95428679Sbrian handle_signals(); 95528679Sbrian continue; 95628679Sbrian } 95728974Sbrian LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 95828679Sbrian break; 9598857Srgrimes } 96023598Sache if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 96126516Sbrian LogPrintf(LogALERT, "Exception detected.\n"); 9626059Samurai break; 9636059Samurai } 96423598Sache if (server >= 0 && FD_ISSET(server, &rfds)) { 96531825Sbrian wfd = accept(server, sa, &ssize); 96624753Sache if (wfd < 0) { 96728974Sbrian LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno)); 96824753Sache continue; 96924753Sache } 97031825Sbrian switch (sa->sa_family) { 97131825Sbrian case AF_LOCAL: 97231825Sbrian LogPrintf(LogPHASE, "Connected to local client.\n"); 97331825Sbrian break; 97431825Sbrian case AF_INET: 97531931Sbrian if (ntohs(sin->sin_port) < 1024) { 97631825Sbrian LogPrintf(LogALERT, "Rejected client connection from %s:%u" 97731825Sbrian "(invalid port number) !\n", 97831931Sbrian inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 97931825Sbrian close(wfd); 98031825Sbrian continue; 98131825Sbrian } 98231825Sbrian LogPrintf(LogPHASE, "Connected to client from %s:%u\n", 98331825Sbrian inet_ntoa(sin->sin_addr), sin->sin_port); 98431825Sbrian break; 98531825Sbrian default: 98631825Sbrian write(wfd, "Unrecognised access !\n", 22); 98731825Sbrian close(wfd); 98831825Sbrian continue; 98931825Sbrian } 99023598Sache if (netfd >= 0) { 99131825Sbrian write(wfd, "Connection already in use.\n", 27); 9926059Samurai close(wfd); 9936059Samurai continue; 99431825Sbrian } 99531825Sbrian netfd = wfd; 99626516Sbrian VarTerm = fdopen(netfd, "a+"); 99731081Sbrian LocalAuthInit(); 99830913Sbrian IsInteractive(1); 99925630Sbrian Prompt(); 10006059Samurai } 100131514Sbrian if (netfd >= 0 && FD_ISSET(netfd, &rfds)) 10026059Samurai /* something to read from tty */ 10036059Samurai ReadTty(); 100431514Sbrian if (modem >= 0 && FD_ISSET(modem, &wfds)) { 100531514Sbrian /* ready to write into modem */ 100631514Sbrian ModemStartOutput(modem); 100731514Sbrian if (modem < 0) 100831514Sbrian dial_up = 1; 10096059Samurai } 101031514Sbrian if (modem >= 0 && FD_ISSET(modem, &rfds)) { 101131514Sbrian /* something to read from modem */ 101231514Sbrian if (LcpFsm.state <= ST_CLOSED) 101331514Sbrian nointr_usleep(10000); 101431962Sbrian n = read(modem, rbuff, sizeof rbuff); 101531514Sbrian if ((mode & MODE_DIRECT) && n <= 0) { 101631514Sbrian DownConnection(); 101731514Sbrian } else 101831514Sbrian LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n); 10196059Samurai 102031514Sbrian if (LcpFsm.state <= ST_CLOSED) { 102131514Sbrian /* 102231514Sbrian * In dedicated mode, we just discard input until LCP is started. 102331514Sbrian */ 102431514Sbrian if (!(mode & MODE_DEDICATED)) { 102531514Sbrian cp = HdlcDetect(rbuff, n); 102631514Sbrian if (cp) { 102731514Sbrian /* 102831514Sbrian * LCP packet is detected. Turn ourselves into packet mode. 102931514Sbrian */ 103031514Sbrian if (cp != rbuff) { 103131514Sbrian write(modem, rbuff, cp - rbuff); 103231514Sbrian write(modem, "\r\n", 2); 103331514Sbrian } 103432658Sbrian PacketMode(0); 103531514Sbrian } else 103631514Sbrian write(fileno(VarTerm), rbuff, n); 10376059Samurai } 103831514Sbrian } else { 103931514Sbrian if (n > 0) 104031514Sbrian AsyncInput(rbuff, n); 10416059Samurai } 10426059Samurai } 104328679Sbrian if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read 104428679Sbrian * from tun */ 104531962Sbrian n = read(tun_in, &tun, sizeof tun); 10466059Samurai if (n < 0) { 104728974Sbrian LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno)); 10486059Samurai continue; 10496059Samurai } 105031962Sbrian n -= sizeof tun - sizeof tun.data; 105131195Sbrian if (n <= 0) { 105231195Sbrian LogPrintf(LogERROR, "read from tun: Only %d bytes read\n", n); 105331195Sbrian continue; 105431195Sbrian } 105531195Sbrian if (!tun_check_header(tun, AF_INET)) 105631195Sbrian continue; 105728679Sbrian if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) { 105828536Sbrian /* we've been asked to send something addressed *to* us :( */ 105928536Sbrian if (VarLoopback) { 106028536Sbrian pri = PacketCheck(rbuff, n, FL_IN); 106128536Sbrian if (pri >= 0) { 106228536Sbrian struct mbuf *bp; 106328679Sbrian 106431343Sbrian#ifndef NOALIAS 106528536Sbrian if (mode & MODE_ALIAS) { 106628536Sbrian VarPacketAliasIn(rbuff, sizeof rbuff); 106728679Sbrian n = ntohs(((struct ip *) rbuff)->ip_len); 106828536Sbrian } 106931343Sbrian#endif 107028536Sbrian bp = mballoc(n, MB_IPIN); 107130715Sbrian memcpy(MBUF_CTOP(bp), rbuff, n); 107228536Sbrian IpInput(bp); 107328536Sbrian LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n"); 107428536Sbrian } 107528536Sbrian continue; 107628679Sbrian } else 107728536Sbrian LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n"); 107828536Sbrian } 107928536Sbrian 10806059Samurai /* 108128679Sbrian * Process on-demand dialup. Output packets are queued within tunnel 108228679Sbrian * device until IPCP is opened. 10836059Samurai */ 108432039Sbrian if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO) && 108532039Sbrian (pri = PacketCheck(rbuff, n, FL_DIAL)) >= 0) 108632039Sbrian dial_up = 1; 108732039Sbrian 10887001Samurai pri = PacketCheck(rbuff, n, FL_OUT); 108920365Sjkh if (pri >= 0) { 109031343Sbrian#ifndef NOALIAS 109128679Sbrian if (mode & MODE_ALIAS) { 109228679Sbrian VarPacketAliasOut(rbuff, sizeof rbuff); 109328679Sbrian n = ntohs(((struct ip *) rbuff)->ip_len); 109428679Sbrian } 109531343Sbrian#endif 10966059Samurai IpEnqueue(pri, rbuff, n); 109720365Sjkh } 10986059Samurai } 10996059Samurai } 110026516Sbrian LogPrintf(LogDEBUG, "Job (DoLoop) done.\n"); 11016059Samurai} 1102