Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Aug 96 10:56 MDT
From:      gord@enci.ucalgary.ca
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/1469: it is difficult to run /usr/sbin/ppp from a script
Message-ID:  <m0unpQK-0006AVC@walter>
Resent-Message-ID: <199608061730.KAA01899@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         1469
>Category:       bin
>Synopsis:       it is difficult to run /usr/sbin/ppp from a script
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug  6 10:30:02 PDT 1996
>Last-Modified:
>Originator:     Gord Matzigkeit
>Organization:
Profit Press
>Release:        FreeBSD 2.1-STABLE i386
>Environment:

FreeBSD walter.profitpress.com 2.1.5-RELEASE
FreeBSD 2.1.5-RELEASE #0: Tue Jul 30 18:58:54 MDT 1996
    gord@walter.profitpress.com:/usr/src/sys/compile/PINT
i386

>Description:

For /usr/sbin/ppp, you must choose between running ppp in the background or
connecting to a host immediately in the foreground.

I would like to be able to run ppp from a script so that my script can be
sure that it is connected to the 'net before it continues running:

  # Dial up the internet.
  ppp -background myprovider || exit 1

  do-some-net-command

  # Hang up the modem.
  kill -HUP `cat /var/run/ppp.tun0.pid`

Another problem is that the current ppp calls its process id file
`/var/run/PPP.server', which may conflict if you have more than one IP
tunnel interface available.

>How-To-Repeat:

>Fix:
	
I have renamed the PID file from `/var/run/PPP.system' to
`/var/run/ppp.device.pid'.

I have also implemented background mode in the ppp daemon.  Here are
the relevant excerpts from the new man page:

SYNOPSIS
     ppp [-auto | -background | -direct]
...

     Supports on-demand dialup capability.  By using auto mode, ppp will act
     as a daemon and wait for a packet to be sent over the PPP link.  When
     this happens, the daemon automatically dials and establishes the connec-
     tion.

     Supports background PPP connections.  In background mode, if ppp success-
     fully establishes the connection, it will become a daemon.  Otherwise, it
     will exit with an error.

     Supports server-side PPP connections.  Can act as server which accepts
     incoming PPP connections.
...
BACKGROUND DIALING
     If you want to establish a connection using ppp non-interactively (such
     as from a crontab(5) entry or an at(1) script) you should use the
     -background option.  You must also specify the destination label in
     /etc/ppp/ppp.conf to use.

     When -background is specified, ppp attempts to establish the connection.
     If this attempt fails, ppp exits immediately with a non-zero exit code.

     If it succeeds, then 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 HUP or TERM signal.

     The file /var/run/ppp.tun0.pid contains the process id number of the ppp
     program that is using the tunnel device tun0.


Here is the patch:

diff -u ppp/command.c.orig ppp/command.c
--- ppp/command.c.orig	Mon Jun 10 09:35:21 1996
+++ ppp/command.c	Wed Jul 31 17:36:25 1996
@@ -159,7 +159,7 @@
 {
   const char *shell;
   pid_t shpid;
-  
+
   if((shell = getenv("SHELL")) == 0) {
     shell = _PATH_BSHELL;
   }
@@ -200,7 +200,7 @@
        execvp(argv[0], argv);
      else
        execl(shell, shell, NULL);
-      
+
      fprintf(stdout, "exec() of %s failed\n", argc > 0? argv[0]: shell);
      exit(255);
   }
@@ -210,9 +210,9 @@
     int status;
     (void)waitpid(shpid, &status, 0);
   }
-  
+
   TtyCommandMode(1);
-      
+
   return(0);
 }
 
@@ -778,7 +778,7 @@
     	if (--argc > 0) {
       		ParseAddr(argc, argv++,
 		        &DefTriggerAddress.ipaddr,
-			&DefTriggerAddress.mask, 
+			&DefTriggerAddress.mask,
 			&DefTriggerAddress.width);
 	}
       }
@@ -984,4 +984,3 @@
   }
   return(1);
 }
-
diff -u ppp/defs.h.orig ppp/defs.h
--- ppp/defs.h.orig	Mon Feb  5 14:36:23 1996
+++ ppp/defs.h	Wed Jul 31 19:18:36 1996
@@ -59,6 +59,7 @@
 #define MODE_AUTO	2	/* Auto calling mode */
 #define	MODE_DIRECT	4	/* Direct connection mode */
 #define	MODE_DEDICATED	8	/* Dedicated line mode */
+#define MODE_BACKGROUND 16	/* Background mode. */
 
 #define	EX_NORMAL	0
 #define	EX_START	1
@@ -71,8 +72,11 @@
 #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;
diff -u ppp/main.c.orig ppp/main.c
--- ppp/main.c.orig	Mon Feb  5 14:36:28 1996
+++ ppp/main.c	Wed Jul 31 19:35:44 1996
@@ -69,6 +69,7 @@
 static struct termios comtio;		/* Command level tty mode */
 static int TermMode;
 static int server;
+static pid_t BGPid = 0;
 struct sockaddr_in ifsin;
 char pid_filename[128];
 
@@ -154,6 +155,8 @@
   sleep(1);
   if (mode & MODE_AUTO) {
     DeleteIfRoutes(1);
+  }
+  if (mode & (MODE_AUTO | MODE_BACKGROUND)) {
     unlink(pid_filename);
   }
   OsInterfaceDown(1);
@@ -169,16 +172,28 @@
 static void
 Hangup()
 {
-  LogPrintf(LOG_PHASE, "SIGHUP\n");
-  Cleanup(EX_HANGUP);
+  if (BGPid) {
+    kill (BGPid, SIGHUP);
+    exit (EX_HANGUP);
+  }
+  else {
+    LogPrintf(LOG_PHASE, "SIGHUP\n");
+    Cleanup(EX_HANGUP);
+  }
 }
 
 static void
 CloseSession()
 {
-  LogPrintf(LOG_PHASE, "SIGTERM\n");
-  LcpClose();
-  Cleanup(EX_TERM);
+  if (BGPid) {
+    kill (BGPid, SIGINT);
+    exit (EX_TERM);
+  }
+  else {
+    LogPrintf(LOG_PHASE, "SIGTERM\n");
+    LcpClose();
+    Cleanup(EX_TERM);
+  }
 }
 
 
@@ -204,7 +219,7 @@
 void
 Usage()
 {
-  fprintf(stderr, "Usage: ppp [-auto | -direct | -dedicated] [system]\n");
+  fprintf(stderr, "Usage: ppp [-auto | -background | -direct | -dedicated] [system]\n");
   exit(EX_START);
 }
 
@@ -219,6 +234,8 @@
     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)
@@ -288,7 +305,7 @@
     exit(EX_START);
   }
 
-  if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED))
+  if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED|MODE_BACKGROUND))
     mode &= ~MODE_INTER;
   if (mode & MODE_INTER) {
     printf("Interactive mode\n");
@@ -299,6 +316,12 @@
       fprintf(stderr, "Destination system must be specified in auto 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 */
@@ -349,36 +372,61 @@
 #endif
 
   if (!(mode & MODE_INTER)) {
-     int port = SERVER_PORT + tunno;
-    /*
-     *  Create server socket and listen at there.
-     */
-    server = socket(PF_INET, SOCK_STREAM, 0);
-    if (server < 0) {
-      perror("socket");
-      Cleanup(EX_SOCK);
+    int port = SERVER_PORT + tunno;
+    if (mode & MODE_BACKGROUND) {
+      if (pipe (BGFiledes)) {
+	perror("pipe");
+	Cleanup(EX_SOCK);
+      }
+      server = -1;
     }
-    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);
+    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);
     }
-    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 (fork())
-        exit(0);
+	if (mode & MODE_BACKGROUND) {
+	  /* Wait for our child to close its pipe before we exit. */
+	  BGPid = bgpid;
+	  read (BGFiledes[0], &c, 1);
+	  if (c == EX_NORMAL)
+	    LogPrintf (LOG_CHAT, "PPP enabled.\n");
+	}
+        exit(c);
+      }
 
-      snprintf(pid_filename, sizeof (pid_filename), "%s/PPP.%s",
-		  _PATH_VARRUN, dstsystem);
+      snprintf(pid_filename, sizeof (pid_filename), "%s/ppp.tun%d.pid",
+		  _PATH_VARRUN, tunno);
       unlink(pid_filename);
       sprintf(pid, "%lu\n", getpid());
 
@@ -388,12 +436,14 @@
 	  close(fd);
       }
     }
-    LogPrintf(LOG_PHASE, "Listening at %d.\n", port);
+    if (server > 0)
+      LogPrintf(LOG_PHASE, "Listening at %d.\n", port);
+
+    if (mode & (MODE_DIRECT
 #ifdef DOTTYINIT
-    if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */
-#else
-    if (mode & MODE_DIRECT) {
+	|MODE_DEDICATED
 #endif
+	)) {
       TtyInit();
     } else {
       setsid();			/* detach control tty */
@@ -414,7 +464,7 @@
 }
 
 /*
- *  Turn into packet mode, where we speek PPP.
+ *  Turn into packet mode, where we speak PPP.
  */
 void
 PacketMode()
diff -u ppp/modem.c.orig ppp/modem.c
--- ppp/modem.c.orig	Mon Feb  5 14:36:30 1996
+++ ppp/modem.c	Wed Jul 31 16:48:08 1996
@@ -724,6 +724,7 @@
 DialModem()
 {
   char ScriptBuffer[200];
+  int excode;
 
   strcpy(ScriptBuffer, VarDialScript);
   if (DoChat(ScriptBuffer) > 0) {
@@ -734,12 +735,20 @@
       return(1);
     } else {
       fprintf(stderr, "login failed.\n");
+      excode = EX_NOLOGIN;
     }
     ModemTimeout();	/* Dummy call to check modem status */
   }
-  else
+  else {
     fprintf(stderr, "dial failed.\n");
+    excode = EX_NODIAL;
+  }
   HangupModem(0);
+  if (mode & MODE_BACKGROUND) {
+    extern void Cleanup();
+    CloseModem();
+    Cleanup(excode);
+  }
   return(0);
 }
 
diff -u ppp/phase.h.orig ppp/phase.h
--- ppp/phase.h.orig	Sun Feb 26 05:17:53 1995
+++ ppp/phase.h	Wed Jul 31 19:57:52 1996
@@ -26,9 +26,10 @@
 
 #define	PHASE_DEAD		0		/* Link is dead */
 #define	PHASE_ESTABLISH		1		/* Establishing link */
-#define	PHASE_AUTHENTICATE	2		/* Beeing authenticate */
+#define	PHASE_AUTHENTICATE	2		/* Being authenticated */
 #define	PHASE_NETWORK		3
 #define	PHASE_TERMINATE		4		/* Terminating link */
+#define PHASE_OSLINKED		5		/* The OS is linked up */
 
 int phase;				/* Curent phase */
 
diff -u ppp/ppp.8.orig ppp/ppp.8
--- ppp/ppp.8.orig	Mon Feb  5 14:36:32 1996
+++ ppp/ppp.8	Wed Jul 31 18:19:18 1996
@@ -9,7 +9,7 @@
 Point to Point Protocol (aka iijppp)
 .Sh SYNOPSIS
 .Nm
-.Op Fl auto \*(Ba Fl direct Fl dedicated
+.Op Fl auto \*(Ba Fl background \*(Ba Fl direct \*(Ba Fl dedicated
 .Sh DESCRIPTION
 This is a user process
 .Em PPP
@@ -31,7 +31,7 @@
 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. 
+.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
@@ -52,11 +52,17 @@
 link.  When this happens, the daemon automatically dials and establishes the
 connection.
 
+.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. 
- 
+connections.
+
 .It Supports PAP and CHAP authentication.
 
 
@@ -69,7 +75,7 @@
 .It Supports packet filtering.
 User can define four kinds of filters:
 .Em ifilter
-for incoming packets, 
+for incoming packets,
 .Em ofilter
 for outgoing packets,
 .Em dfilter
@@ -84,14 +90,14 @@
 .Em PPP
 link.
 
-.It Supports PPP over TCP capability. 
+.It Supports PPP over TCP capability.
 
 
-.It Supports IETF draft Predictor-1 compression.  
+.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. 
+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
@@ -118,7 +124,7 @@
 
 .Dl pseudo-device   tun             1
 
-You should set the numeric field to the maximum number of 
+You should set the numeric field to the maximum number of
 .Em PPP
 connections you wish to support.
 
@@ -130,7 +136,7 @@
 
 .Sh MANUAL DIALING
 
-% 
+%
 .Nm
 User Process PPP written by Toshiharu OHNO.
 
@@ -141,7 +147,7 @@
 
 ppp on "your hostname"> help
   passwd  : Password for security
-  quit    : Quit the PPP program    
+  quit    : Quit the PPP program
   help    : Display this message
 
 ppp on tama> pass <password>
@@ -270,6 +276,39 @@
 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 HUP or 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
@@ -298,7 +337,7 @@
     Connected to localhost.spec.co.jp.
     Escape character is '^]'.
     User Process PPP. Written by Toshiharu OHNO.
-    Working as auto mode. 
+    Working as auto mode.
     PPP on tama> show ipcp
     what ?
     PPP on tama> pass xxxx
@@ -379,11 +418,11 @@
 .Sq filter-name
 should be one of ifilter, ofilter, or dfilter.
 .It
-There are two actions: 
+There are two actions:
 .Sq permit
 and
 .Sq deny .
-If a given packet 
+If a given packet
 matches the rule, the associated action is taken immediately.
 .It
 .Sq src_width
@@ -427,7 +466,7 @@
 connection request, follow these steps:
 
 .Bl -enum
-.It 
+.It
 Make sure the modem and (optionally)
 .Pa /etc/rc.serial
 is configured correctly.
@@ -458,7 +497,7 @@
 .Ed
 
 .It
-Create a 
+Create a
 .Pa /usr/local/bin/ppplogin
 file with the following contents:
 .Bd -literal -offset indent
@@ -491,7 +530,7 @@
 .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. 
+are timeout = 180 or 3 min, lqrtimer = 30sec and retrytimer = 3sec.
 To disable the idle timer function,
 use the command
 .Dq set timeout 0 .
@@ -527,7 +566,7 @@
 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, 
+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
@@ -563,7 +602,7 @@
 .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. 
+all IP addresses and the other side should obey the direction from it.
 .El
 
 In order to allow more flexible behavior, `ifaddr' command allows the
@@ -579,7 +618,7 @@
 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 
+.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.
@@ -718,11 +757,11 @@
 .It /var/log/ppp.log
 Logging and debugging information file.
 
-.It /var/spool/lock/Lck..* 
+.It /var/spool/lock/Lck..*
 tty port locking file.
 
-.It /var/run/PPP.system
-Holds the pid for ppp -auto system.
+.It /var/run/ppp.tun0.pid
+The process id (pid) of the ppp program connected to the ppp0 device.
 
 .It /etc/services
 Get port number if port number is using service name.
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?m0unpQK-0006AVC>