move old kamikaze out of trunk - will put buildroot-ng in there as soon as all the...
[openwrt/openwrt.git] / openwrt / package / l2tpd / patches / 03-jacco-pty.patch
diff --git a/openwrt/package/l2tpd/patches/03-jacco-pty.patch b/openwrt/package/l2tpd/patches/03-jacco-pty.patch
deleted file mode 100644 (file)
index 67169b8..0000000
+++ /dev/null
@@ -1,1194 +0,0 @@
-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;
-+}