From 4fbbef031b45aa1184eac867688a5734dc3f0ef5 Mon Sep 17 00:00:00 2001
From: nico <nico@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Fri, 16 Dec 2005 12:00:19 +0000
Subject: [PATCH] port l2tpd fixes from changeset:2696 to trunk.

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@2697 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 openwrt/package/l2tpd/Makefile                |    8 +-
 openwrt/package/l2tpd/files/l2tpd.conf        |   29 +
 openwrt/package/l2tpd/files/l2tpd.init        |   21 +
 openwrt/package/l2tpd/files/options.l2tpd     |   17 +
 openwrt/package/l2tpd/ipkg/l2tpd.conffiles    |    2 +
 .../{debian-2.patch => 01-debian-2.patch}     |    0
 .../l2tpd/patches/02-debian-2-pty-rev.patch   |   21 +
 .../package/l2tpd/patches/03-jacco-pty.patch  | 1194 +++++++++++++++++
 8 files changed, 1291 insertions(+), 1 deletion(-)
 create mode 100644 openwrt/package/l2tpd/files/l2tpd.conf
 create mode 100644 openwrt/package/l2tpd/files/l2tpd.init
 create mode 100644 openwrt/package/l2tpd/files/options.l2tpd
 create mode 100644 openwrt/package/l2tpd/ipkg/l2tpd.conffiles
 rename openwrt/package/l2tpd/patches/{debian-2.patch => 01-debian-2.patch} (100%)
 create mode 100644 openwrt/package/l2tpd/patches/02-debian-2-pty-rev.patch
 create mode 100644 openwrt/package/l2tpd/patches/03-jacco-pty.patch

diff --git a/openwrt/package/l2tpd/Makefile b/openwrt/package/l2tpd/Makefile
index ac80e0b09..0af0c09f4 100644
--- a/openwrt/package/l2tpd/Makefile
+++ b/openwrt/package/l2tpd/Makefile
@@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=l2tpd
 PKG_VERSION:=0.70pre
 PKG_UPSTREAM_VERSION:=0.70-pre20031121
-PKG_RELEASE:=1
+PKG_RELEASE:=2.1
 PKG_MD5SUM:=3f2707b6e16a8cb72e7bf64f574202fa
 
 PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/l/l2tpd
@@ -30,6 +30,12 @@ $(PKG_BUILD_DIR)/.built:
 	touch $@
 
 $(IPKG_L2TPD):
+	install -d -m0755 $(IDIR_L2TPD)/etc/l2tpd
+	install -m0644 ./files/l2tpd.conf $(IDIR_L2TPD)/etc/l2tpd/
+	install -d -m0755 $(IDIR_L2TPD)/etc/ppp
+	install -m0644 ./files/options.l2tpd $(IDIR_L2TPD)/etc/ppp/
+	install -d -m0755 $(IDIR_L2TPD)/etc/init.d
+	install -m0755 ./files/l2tpd.init $(IDIR_L2TPD)/etc/init.d/l2tpd
 	install -d -m0755 $(IDIR_L2TPD)/usr/sbin
 	install -m0755 $(PKG_BUILD_DIR)/$(PKG_NAME) $(IDIR_L2TPD)/usr/sbin/
 	$(RSTRIP) $(IDIR_L2TPD)
diff --git a/openwrt/package/l2tpd/files/l2tpd.conf b/openwrt/package/l2tpd/files/l2tpd.conf
new file mode 100644
index 000000000..2a9ba1cc6
--- /dev/null
+++ b/openwrt/package/l2tpd/files/l2tpd.conf
@@ -0,0 +1,29 @@
+;
+; This is a minimal sample l2tpd configuration file for use
+; with L2TP over IPsec.
+;
+; The idea is to provide an L2TP daemon to which remote Windows L2TP/IPsec
+; clients connect. In this example, the internal (protected) network 
+; is 192.168.1.0/24.  A special IP range within this network is reserved
+; for the remote clients: 192.168.1.128/25
+; (i.e. 192.168.1.128 ... 192.168.1.254)
+;
+; The listen-addr parameter can be used if you want to bind the L2TP daemon
+; to a specific IP address instead of to all interfaces. For instance,
+; you could bind it to the interface of the internal LAN (e.g. 192.168.1.98
+; in the example below). Yet another IP address (local ip, e.g. 192.168.1.99)
+; will be used by l2tpd as its address on pppX interfaces.
+
+[global]
+; listen-addr = 192.168.1.98
+
+[lns default]
+ip range = 192.168.1.128-192.168.1.254
+local ip = 192.168.1.99
+require chap = yes
+refuse pap = yes
+require authentication = yes
+name = LinuxVPNserver
+ppp debug = yes
+pppoptfile = /etc/ppp/options.l2tpd
+length bit = yes
diff --git a/openwrt/package/l2tpd/files/l2tpd.init b/openwrt/package/l2tpd/files/l2tpd.init
new file mode 100644
index 000000000..f53175799
--- /dev/null
+++ b/openwrt/package/l2tpd/files/l2tpd.init
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+BIN=l2tpd
+DEFAULT=/etc/default/$BIN
+RUN_D=/var/run
+PID_F=$RUN_D/$BIN.pid
+[ -f $DEFAULT ] && . $DEFAULT
+
+case $1 in
+ start)
+  $BIN $OPTIONS
+  ;;
+ stop)
+  [ -f $PID_F ] && kill $(cat $PID_F)
+  ;;
+ *)
+  echo "usage: $0 (start|stop)"
+  exit 1
+esac
+
+exit $?
diff --git a/openwrt/package/l2tpd/files/options.l2tpd b/openwrt/package/l2tpd/files/options.l2tpd
new file mode 100644
index 000000000..425a56e08
--- /dev/null
+++ b/openwrt/package/l2tpd/files/options.l2tpd
@@ -0,0 +1,17 @@
+ipcp-accept-local
+ipcp-accept-remote
+ms-dns  192.168.1.1
+ms-dns  192.168.1.3
+ms-wins 192.168.1.2
+ms-wins 192.168.1.4
+noccp
+auth
+crtscts
+idle 1800
+mtu 1410
+mru 1410
+nodefaultroute
+debug
+lock
+proxyarp
+connect-delay 5000
diff --git a/openwrt/package/l2tpd/ipkg/l2tpd.conffiles b/openwrt/package/l2tpd/ipkg/l2tpd.conffiles
new file mode 100644
index 000000000..1607479cb
--- /dev/null
+++ b/openwrt/package/l2tpd/ipkg/l2tpd.conffiles
@@ -0,0 +1,2 @@
+/etc/l2tpd/l2tpd.conf
+/etc/ppp/options.l2tpd
diff --git a/openwrt/package/l2tpd/patches/debian-2.patch b/openwrt/package/l2tpd/patches/01-debian-2.patch
similarity index 100%
rename from openwrt/package/l2tpd/patches/debian-2.patch
rename to openwrt/package/l2tpd/patches/01-debian-2.patch
diff --git a/openwrt/package/l2tpd/patches/02-debian-2-pty-rev.patch b/openwrt/package/l2tpd/patches/02-debian-2-pty-rev.patch
new file mode 100644
index 000000000..135e17e18
--- /dev/null
+++ b/openwrt/package/l2tpd/patches/02-debian-2-pty-rev.patch
@@ -0,0 +1,21 @@
+diff -ruN l2tpd-0.70pre-old/l2tpd.c l2tpd-0.70pre-new/l2tpd.c
+--- l2tpd-0.70pre-old/l2tpd.c	2005-12-16 12:02:02.000000000 +0100
++++ l2tpd-0.70pre-new/l2tpd.c	2005-12-16 12:14:24.000000000 +0100
+@@ -336,17 +336,10 @@
+         tcgetattr (c->fd, &ptyconf);
+         *(c->oldptyconf) = ptyconf;
+         ptyconf.c_cflag &= ~(ICANON | ECHO);
+-		ptyconf.c_lflag &= ~ECHO;
+         tcsetattr (c->fd, TCSANOW, &ptyconf);
+ 
+         snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
+         fd2 = open (tty, O_RDWR);
+-		if(!fd2)
+-			log(LOG_WARN, "unable to open tty %s", tty);
+-
+-		/* XXX JEF: CHECK ME */
+-		stropt[pos++] = strdup(tty);
+-		stropt[pos] = NULL;
+ 
+ #ifdef USE_KERNEL
+     }
diff --git a/openwrt/package/l2tpd/patches/03-jacco-pty.patch b/openwrt/package/l2tpd/patches/03-jacco-pty.patch
new file mode 100644
index 000000000..67169b8ea
--- /dev/null
+++ b/openwrt/package/l2tpd/patches/03-jacco-pty.patch
@@ -0,0 +1,1194 @@
+diff -ruN l2tpd-0.70pre-old/l2tpd.c l2tpd-0.70pre-new/l2tpd.c
+--- l2tpd-0.70pre-old/l2tpd.c	2005-12-16 12:34:12.000000000 +0100
++++ l2tpd-0.70pre-new/l2tpd.c	2005-12-16 12:34:54.000000000 +0100
+@@ -16,6 +16,7 @@
+  */
+ 
+ #include <stdlib.h>
++#include <sys/types.h>
+ #include <sys/utsname.h>
+ #include <sys/stat.h>
+ #include <sys/wait.h>
+@@ -274,8 +275,8 @@
+ 
+ int start_pppd (struct call *c, struct ppp_opts *opts)
+ {
+-    char a, b;
+-    char tty[80];
++    /* char a, b; */
++    char *tty;
+     char *stropt[80];
+     struct ppp_opts *p;
+ #ifdef USE_KERNEL
+@@ -324,12 +325,45 @@
+     else
+     {
+ #endif
+-        if ((c->fd = getPtyMaster (&a, &b)) < 0)
++	c->fd = open("/dev/ptmx", O_RDWR);
++	if (c->fd == -1)
++	{
++		log (LOG_WARN, "%s: unable to open /dev/ptmx to allocate pty\n",
++				__FUNCTION__);
++		return -EINVAL;
++	} else
++	{
++	    if (grantpt(c->fd))
++	    {
++		log (LOG_WARN, "%s: unable to grantpt() on pty\n",
++				__FUNCTION__);
++		close(c->fd);
++		return -EINVAL;
++	    }
++	    if (unlockpt(c->fd))
++	    {
++		log (LOG_WARN, "%s: unable to unlockpt() on pty\n",
++			__FUNCTION__);
++		close(c->fd);
++		return -EINVAL;
++	    }
++	    tty = ptsname(c->fd);
++	    if (tty == NULL)
++	    {
++		log (LOG_WARN, "%s: unable to obtain name of slave tty\n",
++			__FUNCTION__);
++		close(c->fd);
++		return -EINVAL;
++	    }
++	}
++	
++	
++ /*	if ((c->fd = getPtyMaster (&a, &b)) < 0)
+         {
+             log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n",
+                  __FUNCTION__);
+             return -EINVAL;
+-        }
++        } */
+ 
+         /* set fd opened above to not echo so we don't see read our own packets
+            back of the file descriptor that we just wrote them to */
+@@ -338,8 +372,14 @@
+         ptyconf.c_cflag &= ~(ICANON | ECHO);
+         tcsetattr (c->fd, TCSANOW, &ptyconf);
+ 
+-        snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
++/*        snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); */
+         fd2 = open (tty, O_RDWR);
++	if (fd2 == -1)
++	{
++		log (LOG_WARN, "%s: unable to open slave tty %s\n", __FUNCTION__, tty);
++		close(c->fd);
++		return -EINVAL;
++	}
+ 
+ #ifdef USE_KERNEL
+     }
+diff -ruN l2tpd-0.70pre-old/l2tpd.c.orig l2tpd-0.70pre-new/l2tpd.c.orig
+--- l2tpd-0.70pre-old/l2tpd.c.orig	1970-01-01 01:00:00.000000000 +0100
++++ l2tpd-0.70pre-new/l2tpd.c.orig	2005-12-16 12:14:24.000000000 +0100
+@@ -0,0 +1,1104 @@
++/*
++ * $Id$
++ *
++ * Layer Two Tunnelling Protocol Daemon
++ * Copyright (C) 1998 Adtran, Inc.
++ * Copyright (C) 2002 Jeff McAdams
++ *
++ * Mark Spencer
++ *
++ * This software is distributed under the terms
++ * of the GPL, which you should have received
++ * along with this source.
++ *
++ * Main Daemon source.
++ *
++ */
++
++#include <stdlib.h>
++#include <sys/utsname.h>
++#include <sys/stat.h>
++#include <sys/wait.h>
++#include <stdio.h>
++#include <errno.h>
++#include <unistd.h>
++#include <time.h>
++#if (__GLIBC__ < 2)
++# if defined(FREEBSD)
++#  include <sys/signal.h>
++# elif defined(LINUX)
++#  include <bsd/signal.h>
++# elif defined(SOLARIS)
++#  include <signal.h>
++# endif
++#else
++# include <signal.h>
++#endif
++#include <netdb.h>
++#include <string.h>
++#include <fcntl.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#ifdef USE_KERNEL
++#include <sys/ioctl.h>
++#endif
++#include "l2tp.h"
++
++struct tunnel_list tunnels;
++int max_tunnels = DEF_MAX_TUNNELS;
++struct utsname uts;
++int ppd = 1;                    /* Packet processing delay */
++int control_fd;                 /* descriptor of control area */
++char *args;
++
++char *dial_no_tmp;              /* jz: Dialnumber for Outgoing Call */
++int switch_io = 0;              /* jz: Switch for Incoming or Outgoing Call */
++
++void init_tunnel_list (struct tunnel_list *t)
++{
++    t->head = NULL;
++    t->count = 0;
++    t->calls = 0;
++}
++
++/* Now sends to syslog instead - MvO */
++void show_status (void)
++{
++    struct schedule_entry *se;
++    struct tunnel *t;
++    struct call *c;
++    struct lns *tlns;
++    struct lac *tlac;
++    struct host *h;
++    int s = 0;
++    log (LOG_WARN, "====== l2tpd statistics ========\n");
++    log (LOG_WARN, " Scheduler entries:\n");
++    se = events;
++    while (se)
++    {
++        s++;
++        t = (struct tunnel *) se->data;
++        tlac = (struct lac *) se->data;
++        c = (struct call *) se->data;
++        if (se->func == &hello)
++        {
++            log (LOG_WARN, "%d: HELLO to %d\n", s, t->tid);
++        }
++        else if (se->func == &magic_lac_dial)
++        {
++            log (LOG_WARN, "%d: Magic dial on %s\n", s, tlac->entname);
++        }
++        else if (se->func == &send_zlb)
++        {
++            log (LOG_WARN, "%d: Send payload ZLB on call %d:%d\n", s,
++                     c->container->tid, c->cid);
++        }
++        else if (se->func == &dethrottle)
++        {
++            log (LOG_WARN, "%d: Dethrottle call %d:%d\n", s, c->container->tid,
++                     c->cid);
++        }
++        else
++            log (LOG_WARN, "%d: Unknown event\n", s);
++        se = se->next;
++    };
++    log (LOG_WARN, "Total Events scheduled: %d\n", s);
++    log (LOG_WARN, "Number of tunnels open: %d\n", tunnels.count);
++    t = tunnels.head;
++    while (t)
++    {
++        log (LOG_WARN, "Tunnel %s, ID = %d (local), %d (remote) to %s:%d\n"
++                 "   control_seq_num = %d, control_rec_seq_num = %d,\n"
++                 "   cLr = %d\n",
++                 (t->lac ? t->lac->entname : (t->lns ? t->lns->entname : "")),
++                 t->ourtid, t->tid, IPADDY (t->peer.sin_addr),
++                 ntohs (t->peer.sin_port), t->control_seq_num,
++                 t->control_rec_seq_num, t->cLr);
++        c = t->call_head;
++        while (c)
++        {
++            log (LOG_WARN, 
++                     "Call %s, ID = %d (local), %d (remote), serno = %u,\n"
++                     "      data_seq_num = %d, data_rec_seq_num = %d,\n"
++                     "      pLr = %d, tx = %u bytes (%u), rx= %u bytes (%u)\n",
++                     (c->lac ? c->lac->
++                      entname : (c->lns ? c->lns->entname : "")), c->ourcid,
++                     c->cid, c->serno, c->data_seq_num, c->data_rec_seq_num,
++                     c->pLr, c->tx_bytes, c->tx_pkts, c->rx_bytes, c->rx_pkts);
++            c = c->next;
++        }
++        t = t->next;
++    }
++    log (LOG_WARN, "==========Config File===========\n");
++    tlns = lnslist;
++    while (tlns)
++    {
++        log (LOG_WARN, "LNS entry %s\n",
++                 tlns->entname[0] ? tlns->entname : "(unnamed)");
++        tlns = tlns->next;
++    };
++    tlac = laclist;
++    while (tlac)
++    {
++        log (LOG_WARN, "LAC entry %s, LNS is/are:",
++                 tlac->entname[0] ? tlac->entname : "(unnamed)");
++        h = tlac->lns;
++        if (h)
++        {
++            while (h)
++            {
++                log (LOG_WARN, " %s", h->hostname);
++                h = h->next;
++            }
++        }
++        else
++            log (LOG_WARN, " [none]");
++        log (LOG_WARN, "\n");
++        tlac = tlac->next;
++    };
++    log (LOG_WARN, "================================\n");
++}
++
++void null_handler(int sig)
++{
++       /* FIXME 
++        * A sighup is received when a call is terminated, unknown origine .. 
++        * I catch it and ll looks good, but .. 
++	*/
++}
++
++void status_handler (int sig)
++{
++    show_status ();
++}
++
++void child_handler (int signal)
++{
++    /*
++     * Oops, somebody we launched was killed.
++     * It's time to reap them and close that call.
++     * But first, we have to find out what PID died.
++     * unfortunately, pppd will 
++     */
++    struct tunnel *t;
++    struct call *c;
++    pid_t pid;
++    int status;
++    t = tunnels.head;
++    /* Keep looping until all are cleared */
++    for(;;)
++    {
++        pid = waitpid (-1, &status, WNOHANG);
++        if (pid < 1)
++        {
++            /*
++             * Oh well, nobody there.  Maybe we reaped it
++             * somewhere else already
++             */
++            return;
++        }
++        while (t)
++        {
++            c = t->call_head;
++            while (c)
++            {
++                if (c->pppd == pid)
++                {
++                    if ( WIFEXITED( status ) )
++                    {
++                        log (LOG_DEBUG, "%s : pppd exited for call %d with code %d\n", __FUNCTION__,
++                         c->cid, WEXITSTATUS( status ) );
++                    }
++                    else if( WIFSIGNALED( status ) )
++                    {
++                        log (LOG_DEBUG, "%s : pppd terminated for call %d by signal %d\n", __FUNCTION__,
++                         c->cid, WTERMSIG( status ) );
++                    }
++                    else
++                    {
++                        log (LOG_DEBUG, "%s : pppd exited for call %d for unknown reason\n", __FUNCTION__,
++                         c->cid );
++                    }
++                    c->needclose = -1;
++                    /* 
++                     * OK...pppd died, we can go ahead and close the pty for
++                     * it
++                     */
++                    close (c->fd);
++                    c->fd = -1;
++                    return;
++                }
++                c = c->next;
++            }
++            t = t->next;
++        }
++    }
++}
++
++void death_handler (int signal)
++{
++    /*
++       * If we get here, somebody terminated us with a kill or a control-c.
++       * we call call_close on each tunnel twice to get a StopCCN out
++       * for each one (we can't pause to make sure it's received.
++       * Then we close the connections
++     */
++    struct tunnel *st, *st2;
++    int sec;
++    log (LOG_CRIT, "%s: Fatal signal %d received\n", __FUNCTION__, signal);
++    st = tunnels.head;
++    while (st)
++    {
++        st2 = st->next;
++        strcpy (st->self->errormsg, "Server closing");
++        sec = st->self->closing;
++        if (st->lac)
++            st->lac->redial = 0;
++        call_close (st->self);
++        if (!sec)
++        {
++            st->self->closing = -1;
++            call_close (st->self);
++        }
++        st = st2;
++    }
++
++    /* erase pid file */
++	unlink (gconfig.pidfile);
++
++	/* erase control pipe */
++	unlink(CONTROL_PIPE);
++
++    exit (1);
++}
++
++int start_pppd (struct call *c, struct ppp_opts *opts)
++{
++    char a, b;
++    char tty[80];
++    char *stropt[80];
++    struct ppp_opts *p;
++#ifdef USE_KERNEL
++    struct l2tp_call_opts co;
++#endif
++    int pos = 1;
++    int fd2;
++#ifdef DEBUG_PPPD
++    int x;
++#endif
++    struct termios ptyconf;
++    char *str;
++    p = opts;
++    stropt[0] = strdup (PPPD);
++    while (p)
++    {
++        stropt[pos] = (char *) malloc (strlen (p->option) + 1);
++        strncpy (stropt[pos], p->option, strlen (p->option) + 1);
++        pos++;
++        p = p->next;
++    }
++    stropt[pos] = NULL;
++    if (c->pppd > 0)
++    {
++        log (LOG_WARN, "%s: PPP already started on call!\n", __FUNCTION__);
++        return -EINVAL;
++    }
++    if (c->fd > -1)
++    {
++        log (LOG_WARN, "%s: file descriptor already assigned!\n",
++             __FUNCTION__);
++        return -EINVAL;
++    }
++#ifdef USE_KERNEL
++    if (kernel_support)
++    {
++        co.ourtid = c->container->ourtid;
++        co.ourcid = c->ourcid;
++        ioctl (server_socket, L2TPIOCGETCALLOPTS, &co);
++        stropt[pos++] = strdup ("channel");
++        stropt[pos] = (char *) malloc (10);
++        snprintf (stropt[pos], 10, "%d", co.id);
++        pos++;
++        stropt[pos] = NULL;
++    }
++    else
++    {
++#endif
++        if ((c->fd = getPtyMaster (&a, &b)) < 0)
++        {
++            log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n",
++                 __FUNCTION__);
++            return -EINVAL;
++        }
++
++        /* set fd opened above to not echo so we don't see read our own packets
++           back of the file descriptor that we just wrote them to */
++        tcgetattr (c->fd, &ptyconf);
++        *(c->oldptyconf) = ptyconf;
++        ptyconf.c_cflag &= ~(ICANON | ECHO);
++        tcsetattr (c->fd, TCSANOW, &ptyconf);
++
++        snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
++        fd2 = open (tty, O_RDWR);
++
++#ifdef USE_KERNEL
++    }
++#endif
++    str = stropt[0];
++#ifdef DEBUG_PPPD
++    log (LOG_DEBUG, "%s: I'm running:  ", __FUNCTION__);
++    for (x = 0; stropt[x]; x++)
++    {
++        log (LOG_DEBUG, "\"%s\" ", stropt[x]);
++    };
++    log (LOG_DEBUG, "\n");
++#endif
++    c->pppd = fork ();
++    if (c->pppd < 0)
++    {
++        log (LOG_WARN, "%s: unable to fork(), abandoning!\n", __FUNCTION__);
++        return -EINVAL;
++    }
++    else if (!c->pppd)
++    {
++        struct call *sc;
++        struct tunnel *st;
++
++        close (0);
++        close (1);
++        close (2);
++#ifdef USE_KERNEL
++        if (!kernel_support && (fd2 < 0))
++#else
++        if (fd2 < 0)
++#endif
++        {
++            log (LOG_WARN, "%s: Unable to open %s to launch pppd!\n",
++                 __FUNCTION__, tty);
++            exit (1);
++        }
++        dup2 (fd2, 0);
++        dup2 (fd2, 1);
++
++
++        /* close all the calls pty fds */
++        st = tunnels.head;
++        while (st)
++        {
++            sc = st->call_head;
++            while (sc)
++            {
++                close (sc->fd);
++                sc = sc->next;
++            }
++            st = st->next;
++        }
++
++        /* close the UDP socket fd */
++        close (server_socket);
++
++        /* close the control pipe fd */
++        close (control_fd);
++
++        if( c->dialing[0] )
++        {
++            setenv( "CALLER_ID", c->dialing, 1 );
++        }
++        execv (PPPD, stropt);
++        log (LOG_WARN, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD);
++        exit (1);
++    };
++    close (fd2);
++    pos = 0;
++    while (stropt[pos])
++    {
++        free (stropt[pos]);
++        pos++;
++    };
++    return 0;
++}
++
++void destroy_tunnel (struct tunnel *t)
++{
++    /*
++     * Immediately destroy a tunnel (and all its calls)
++     * and free its resources.  This may be called
++     * by the tunnel itself,so it needs to be
++     * "suicide safe"
++     */
++
++    struct call *c, *me;
++    struct tunnel *p;
++    struct timeval tv;
++    if (!t)
++        return;
++
++    /*
++     * Save ourselves until the very
++     * end, since we might be calling this ourselves.
++     * We must divorce ourself from the tunnel
++     * structure, however, to avoid recursion
++     * because of the logic of the destroy_call
++     */
++    me = t->self;
++
++    /*
++     * Destroy all the member calls
++     */
++    c = t->call_head;
++    while (c)
++    {
++        destroy_call (c);
++        c = c->next;
++    };
++    /*
++     * Remove ourselves from the list of tunnels
++     */
++
++    if (tunnels.head == t)
++    {
++        tunnels.head = t->next;
++        tunnels.count--;
++    }
++    else
++    {
++        p = tunnels.head;
++        if (p)
++        {
++            while (p->next && (p->next != t))
++                p = p->next;
++            if (p->next)
++            {
++                p->next = t->next;
++                tunnels.count--;
++            }
++            else
++            {
++                log (LOG_WARN,
++                     "%s: unable to locate tunnel in tunnel list\n",
++                     __FUNCTION__);
++            }
++        }
++        else
++        {
++            log (LOG_WARN, "%s: tunnel list is empty!\n", __FUNCTION__);
++        }
++    }
++    if (t->lac)
++    {
++        t->lac->t = NULL;
++        if (t->lac->redial && (t->lac->rtimeout > 0) && !t->lac->rsched &&
++            t->lac->active)
++        {
++            log (LOG_LOG, "%s: Will redial in %d seconds\n", __FUNCTION__,
++                 t->lac->rtimeout);
++            tv.tv_sec = t->lac->rtimeout;
++            tv.tv_usec = 0;
++            t->lac->rsched = schedule (tv, magic_lac_dial, t->lac);
++        }
++    }
++    /* XXX L2TP/IPSec: remove relevant SAs here?  NTB 20011010
++     * XXX But what if another tunnel is using same SA?
++     */
++    if (t->lns)
++        t->lns->t = NULL;
++    free (t);
++    free (me);
++}
++
++struct tunnel *l2tp_call (char *host, int port, struct lac *lac,
++                          struct lns *lns)
++{
++    /*
++     * Establish a tunnel from us to host
++     * on port port
++     */
++    struct call *tmp = NULL;
++    struct hostent *hp;
++    unsigned int addr;
++    port = htons (port);
++    hp = gethostbyname (host);
++    if (!hp)
++    {
++        log (LOG_WARN, "%s: gethostbyname() failed for %s.\n", __FUNCTION__,
++             host);
++        return NULL;
++    }
++    bcopy (hp->h_addr, &addr, hp->h_length);
++    /* Force creation of a new tunnel
++       and set it's tid to 0 to cause
++       negotiation to occur */
++    /* XXX L2TP/IPSec: Set up SA to addr:port here?  NTB 20011010
++     */
++    tmp = get_call (0, 0, addr, port);
++    if (!tmp)
++    {
++        log (LOG_WARN, "%s: Unable to create tunnel to %s.\n", __FUNCTION__,
++             host);
++        return NULL;
++    }
++    tmp->container->tid = 0;
++    tmp->container->lac = lac;
++    tmp->container->lns = lns;
++    tmp->lac = lac;
++    tmp->lns = lns;
++    if (lac)
++        lac->t = tmp->container;
++    if (lns)
++        lns->t = tmp->container;
++    /*
++     * Since our state is 0, we will establish a tunnel now
++     */
++    log (LOG_LOG, "%s:Connecting to host %s, port %d\n", __FUNCTION__, host,
++         ntohs (port));
++    control_finish (tmp->container, tmp);
++    return tmp->container;
++}
++
++void magic_lac_tunnel (void *data)
++{
++    struct lac *lac;
++    lac = (struct lac *) data;
++    if (!lac)
++    {
++        log (LOG_WARN, "%s: magic_lac_tunnel: called on NULL lac!\n",
++             __FUNCTION__);
++        return;
++    }
++    if (lac->lns)
++    {
++        /* FIXME: I should try different LNS's if I get failures */
++        l2tp_call (lac->lns->hostname, lac->lns->port, lac, NULL);
++        return;
++    }
++    else if (deflac && deflac->lns)
++    {
++        l2tp_call (deflac->lns->hostname, deflac->lns->port, lac, NULL);
++        return;
++    }
++    else
++    {
++        log (LOG_WARN, "%s: Unable to find hostname to dial for '%s'\n",
++             __FUNCTION__, lac->entname);
++        return;
++    }
++}
++
++struct call *lac_call (int tid, struct lac *lac, struct lns *lns)
++{
++    struct tunnel *t = tunnels.head;
++    struct call *tmp;
++    while (t)
++    {
++        if (t->ourtid == tid)
++        {
++            tmp = new_call (t);
++            if (!tmp)
++            {
++                log (LOG_WARN, "%s: unable to create new call\n",
++                     __FUNCTION__);
++                return NULL;
++            }
++            tmp->next = t->call_head;
++            t->call_head = tmp;
++            t->count++;
++            tmp->cid = 0;
++            tmp->lac = lac;
++            tmp->lns = lns;
++            if (lac)
++                lac->c = tmp;
++            log (LOG_LOG, "%s: Calling on tunnel %d\n", __FUNCTION__, tid);
++            strcpy (tmp->dial_no, dial_no_tmp); /*  jz: copy dialnumber to tmp->dial_no  */
++            control_finish (t, tmp);
++            return tmp;
++        }
++        t = t->next;
++    };
++    log (LOG_DEBUG, "%s: No such tunnel %d to generate call.\n", __FUNCTION__,
++         tid);
++    return NULL;
++}
++
++void magic_lac_dial (void *data)
++{
++    struct lac *lac;
++    lac = (struct lac *) data;
++
++    if (!lac)
++    {
++        log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__);
++        return;
++    }
++	if (!lac->active)
++    {
++        log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname);
++        return;
++    }
++    lac->rsched = NULL;
++    lac->rtries++;
++    if (lac->rmax && (lac->rtries > lac->rmax))
++    {
++        log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__);
++        return;
++    }
++    if (!lac->t)
++    {
++#ifdef DEGUG_MAGIC
++        log (LOG_DEBUG, "%s : tunnel not up!  Connecting!\n", __FUNCTION__);
++#endif
++        magic_lac_tunnel (lac);
++        return;
++    }
++    lac_call (lac->t->ourtid, lac, NULL);
++}
++
++void lac_hangup (int cid)
++{
++    struct tunnel *t = tunnels.head;
++    struct call *tmp;
++    while (t)
++    {
++        tmp = t->call_head;
++        while (tmp)
++        {
++            if (tmp->ourcid == cid)
++            {
++                log (LOG_LOG,
++                     "%s :Hanging up call %d, Local: %d, Remote: %d\n",
++                     __FUNCTION__, tmp->serno, tmp->ourcid, tmp->cid);
++                strcpy (tmp->errormsg, "Goodbye!");
++/*				tmp->needclose = -1; */
++                kill (tmp->pppd, SIGTERM);
++                return;
++            }
++            tmp = tmp->next;
++        }
++        t = t->next;
++    };
++    log (LOG_DEBUG, "%s : No such call %d to hang up.\n", __FUNCTION__, cid);
++    return;
++}
++
++void lac_disconnect (int tid)
++{
++    struct tunnel *t = tunnels.head;
++    while (t)
++    {
++        if (t->ourtid == tid)
++        {
++            log (LOG_LOG,
++                 "%s: Disconnecting from %s, Local: %d, Remote: %d\n",
++                 __FUNCTION__, IPADDY (t->peer.sin_addr), t->ourtid, t->tid);
++            t->self->needclose = -1;
++            strcpy (t->self->errormsg, "Goodbye!");
++            call_close (t->self);
++            return;
++        }
++        t = t->next;
++    };
++    log (LOG_DEBUG, "%s: No such tunnel %d to hang up.\n", __FUNCTION__, tid);
++    return;
++}
++
++struct tunnel *new_tunnel ()
++{
++    struct tunnel *tmp = malloc (sizeof (struct tunnel));
++    char entropy_buf[2] = "\0";
++    if (!tmp)
++        return NULL;
++    tmp->control_seq_num = 0;
++    tmp->control_rec_seq_num = 0;
++    tmp->cLr = 0;
++    tmp->call_head = NULL;
++    tmp->next = NULL;
++    tmp->debug = -1;
++    tmp->tid = -1;
++    tmp->hello = NULL;
++#ifndef TESTING
++/*	while(get_call((tmp->ourtid = rand() & 0xFFFF),0,0,0)); */
++#ifdef USE_KERNEL
++    if (kernel_support)
++        tmp->ourtid = ioctl (server_socket, L2TPIOCADDTUNNEL, 0);
++    else
++#endif
++/*        tmp->ourtid = rand () & 0xFFFF; */
++        /* get_entropy((char *)&tmp->ourtid, 2); */
++        get_entropy(entropy_buf, 2);
++        {
++            int *temp;
++            temp = (int *)entropy_buf;
++            tmp->ourtid = *temp & 0xFFFF;
++#ifdef DEBUG_ENTROPY
++            log(LOG_DEBUG, "ourtid = %u, entropy_buf = %hx\n", tmp->ourtid, *temp);
++#endif
++        }
++#else
++    tmp->ourtid = 0x6227;
++#endif
++    tmp->nego = 0;
++    tmp->count = 0;
++    tmp->state = 0;             /* Nothing */
++    tmp->peer.sin_family = AF_INET;
++    tmp->peer.sin_port = 0;
++    bzero (&(tmp->peer.sin_addr), sizeof (tmp->peer.sin_addr));
++    tmp->sanity = -1;
++    tmp->qtid = -1;
++    tmp->ourfc = ASYNC_FRAMING | SYNC_FRAMING;
++    tmp->ourbc = 0;
++    tmp->ourtb = (((_u64) rand ()) << 32) | ((_u64) rand ());
++    tmp->fc = -1;               /* These really need to be specified by the peer */
++    tmp->bc = -1;               /* And we want to know if they forgot */
++    tmp->hostname[0] = 0;
++    tmp->vendor[0] = 0;
++    tmp->secret[0] = 0;
++    if (!(tmp->self = new_call (tmp)))
++    {
++        free (tmp);
++        return NULL;
++    };
++    tmp->ourrws = DEFAULT_RWS_SIZE;
++    tmp->self->ourfbit = FBIT;
++    tmp->lac = NULL;
++    tmp->lns = NULL;
++    tmp->chal_us.state = 0;
++    tmp->chal_us.secret[0] = 0;
++    memset (tmp->chal_us.reply, 0, MD_SIG_SIZE);
++    tmp->chal_them.state = 0;
++    tmp->chal_them.secret[0] = 0;
++    memset (tmp->chal_them.reply, 0, MD_SIG_SIZE);
++    tmp->chal_them.vector = (unsigned char *) malloc (VECTOR_SIZE);
++    tmp->chal_us.vector = NULL;
++    tmp->hbit = 0;
++    return tmp;
++}
++
++void do_control ()
++{
++    char buf[1024];
++    char *host, *tunstr, *callstr, *tmpstr;
++    struct lac *lac;
++    int call;
++    int tunl;
++    int cnt = -1;
++    while (cnt)
++    {
++        cnt = read (control_fd, buf, sizeof (buf));
++        if (cnt > 0)
++        {
++            if (buf[cnt - 1] == '\n')
++                buf[--cnt] = 0;
++#ifdef DEBUG_CONTROL
++            log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n",
++                 __FUNCTION__, buf, cnt);
++#endif
++            switch (buf[0])
++            {
++            case 't':
++                host = strchr (buf, ' ');
++				if(!host)
++					goto out;
++				host++;
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
++                     __FUNCTION__, host);
++#endif
++                l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
++                break;
++            case 'c':		   /* option 'c' for incoming call */
++            case 'o':          /* option 'o' for outgoing call */
++				tunstr = strchr (buf, ' ');
++				if(!tunstr)
++					goto out;
++				tunstr++;
++
++				if(buf[0] == 'c')
++                	switch_io = 1;  /* Switch for Incoming Calls */
++				else {
++                	switch_io = 0;  /* Switch for Outgoing Calls */
++					tmpstr = strchr(tunstr, ' ');
++					if(!tmpstr)
++						goto out;
++					strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp));
++				}
++                
++                lac = laclist;
++                while (lac)
++                {
++                    if (!strcasecmp (lac->entname, tunstr))
++                    {
++                        lac->active = -1;
++                        lac->rtries = 0;
++                        if (!lac->c)
++                            magic_lac_dial (lac);
++                        else
++                            log (LOG_DEBUG,
++                                 "%s: Session '%s' already active!\n",
++                                 __FUNCTION__, lac->entname);
++                        break;
++                    }
++                    lac = lac->next;
++                }
++                if (lac)
++                    break;
++                tunl = atoi (tunstr);
++                if (!tunl)
++                {
++                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
++                         tunstr);
++                    break;
++                }
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
++                     __FUNCTION__, tunl);
++#endif
++                lac_call (tunl, NULL, NULL);
++                break;
++            case 'h':
++                callstr = strchr (buf, ' ');
++                if(!callstr)
++					goto out;
++				callstr++;
++
++                call = atoi (callstr);
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__,
++                     call);
++#endif
++                lac_hangup (call);
++                break;
++            case 'd':
++                tunstr = strchr (buf, ' ');
++                if(!tunstr)
++					goto out;
++				tunstr++;
++
++                lac = laclist;
++                while (lac)
++                {
++                    if (!strcasecmp (lac->entname, tunstr))
++                    {
++                        lac->active = 0;
++                        lac->rtries = 0;
++                        if (lac->t)
++                            lac_disconnect (lac->t->ourtid);
++                        else
++                            log (LOG_DEBUG, "%s: Session '%s' not up\n",
++                                 __FUNCTION__, lac->entname);
++                        break;
++                    }
++                    lac = lac->next;
++                }
++                if (lac)
++                    break;
++                tunl = atoi (tunstr);
++                if (!tunl)
++                {
++                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
++                         tunstr);
++                    break;
++                }
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n",
++                     __FUNCTION__, tunl);
++#endif
++                lac_disconnect (tunl);
++                break;
++            case 's':
++                show_status ();
++                break;
++            default:
++                log (LOG_DEBUG, "%s: Unknown command %c\n", __FUNCTION__,
++                     buf[0]);
++            }
++        }
++    }
++
++out:
++    /* Otherwise select goes nuts */
++    close (control_fd);
++    control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
++}
++
++void usage(void) {
++    printf("Usage: l2tpd -D -c [config file] -s [secret file] -p [pid file]\n");
++    printf("\n");
++    exit(1);
++}
++
++void init_args(int argc, char *argv[]) {
++    int i=0;
++    gconfig.daemon=1;
++    memset(gconfig.altauthfile,0,STRLEN);
++    memset(gconfig.altconfigfile,0,STRLEN);
++    memset(gconfig.authfile,0,STRLEN);
++    memset(gconfig.configfile,0,STRLEN);
++    memset(gconfig.pidfile,0,STRLEN);
++    strncpy(gconfig.altauthfile,ALT_DEFAULT_AUTH_FILE,
++            sizeof(gconfig.altauthfile) - 1);
++    strncpy(gconfig.altconfigfile,ALT_DEFAULT_CONFIG_FILE,
++            sizeof(gconfig.altconfigfile) - 1);
++    strncpy(gconfig.authfile,DEFAULT_AUTH_FILE,
++            sizeof(gconfig.authfile) - 1);
++    strncpy(gconfig.configfile,DEFAULT_CONFIG_FILE,
++            sizeof(gconfig.configfile) - 1);
++    strncpy(gconfig.pidfile,DEFAULT_PID_FILE,
++            sizeof(gconfig.pidfile) - 1);
++    for (i = 1; i < argc; i++) {
++        if(! strncmp(argv[i],"-c",2)) {
++            if(++i == argc)
++                usage();
++            else
++                strncpy(gconfig.configfile,argv[i],
++                        sizeof(gconfig.configfile) - 1);
++        }
++        else if (! strncmp(argv[i],"-D",2)) {
++            gconfig.daemon=0;
++        }
++        else if (! strncmp(argv[i],"-s",2)) {
++            if(++i == argc)
++                usage();
++            else
++                strncpy(gconfig.authfile,argv[i],
++                        sizeof(gconfig.authfile) - 1);
++        }
++        else if (! strncmp(argv[i],"-p",2)) {
++            if(++i == argc)
++                usage();
++            else
++                strncpy(gconfig.pidfile,argv[i],
++                        sizeof(gconfig.pidfile) - 1);
++        }
++        else {
++            usage();
++        }
++    }
++}
++
++
++void daemonize() {
++    int pid=0;
++    int i,l;
++    char buf[STRLEN];
++
++    if((pid = fork()) < 0) {
++        log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__);
++        close(server_socket);
++        exit(1);
++    }
++    else if (pid)
++        exit(0);
++
++
++	close(0);
++	close(1);
++	close(2);
++	dup2(open("/dev/null", O_RDONLY), 0);
++	dup2(open("/dev/null", O_RDONLY), 1);
++	dup2(open("/dev/null", O_RDONLY), 2);
++
++    /* Read previous pid file. */
++    if((i = open(gconfig.pidfile,O_RDONLY)) > 0) {
++		l=read(i,buf,sizeof(buf)-1);                                                             
++        if (l >= 0) {
++        	buf[l] = '\0';                                                                       
++        	pid = atoi(buf);                                                                     
++        }
++		close(i);
++
++		/* if pid is read and process exist exit */
++        if(pid && !kill(pid, 0)) {
++            log(LOG_LOG, "%s: There's already a l2tpd server running.\n",
++                    __FUNCTION__);
++            close(server_socket);
++            exit(1);
++        }
++
++		/* remove stalled pid file */
++		unlink(gconfig.pidfile);
++    }
++
++    pid = setsid();
++
++	/* create new pid file */
++	if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) {
++		snprintf (buf, sizeof(buf), "%d", (int)getpid());
++		write (i, buf, strlen(buf));
++		close (i);
++	}
++	else {
++		log(LOG_LOG, "%s: could not write pid file %s error %d",
++				__FUNCTION__, gconfig.pidfile, i);
++		close(server_socket);
++		exit(1);
++	}
++}
++
++
++void init (int argc,char *argv[])
++{
++    struct lac *lac;
++    struct in_addr listenaddr;
++
++    init_args (argc,argv);
++    srand( time(NULL) );
++    rand_source = 0;
++    init_addr ();
++    if (init_config ())
++    {
++        log (LOG_CRIT, "%s: Unable to load config file\n", __FUNCTION__);
++        exit (1);
++    }
++    if (uname (&uts))
++    {
++        log (LOG_CRIT, "%s : Unable to determine host system\n",
++             __FUNCTION__);
++        exit (1);
++    }
++    init_tunnel_list (&tunnels);
++    if (init_network ())
++        exit (1);
++    if (gconfig.daemon)
++	daemonize ();
++    signal (SIGTERM, &death_handler);
++    signal (SIGINT, &death_handler);
++    signal (SIGCHLD, &child_handler);
++    signal (SIGUSR1, &status_handler);
++    signal (SIGHUP, &null_handler);
++    init_scheduler ();
++    mkfifo (CONTROL_PIPE, 0600);
++    control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
++    if (control_fd < 0)
++    {
++        log (LOG_CRIT, "%s: Unable to open " CONTROL_PIPE " for reading.",
++             __FUNCTION__);
++        exit (1);
++    }
++    log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n",
++         hostname, getpid ());
++    listenaddr.s_addr = gconfig.listenaddr;
++    log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname,
++       uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port);
++    lac = laclist;
++    while (lac)
++    {
++        if (lac->autodial)
++        {
++#ifdef DEBUG_MAGIC
++            log (LOG_DEBUG, "%s: Autodialing '%s'\n", __FUNCTION__,
++                 lac->entname[0] ? lac->entname : "(unnamed)");
++#endif
++            lac->active = -1;
++            switch_io = 1;      /* If we're a LAC, autodials will be ICRQ's */
++            magic_lac_dial (lac);
++        }
++        lac = lac->next;
++    }
++}
++
++int main (int argc, char *argv[])
++{
++    init(argc,argv);
++    dial_no_tmp = calloc (128, sizeof (char));
++    network_thread ();
++    return 0;
++}
-- 
2.20.1