diff options
Diffstat (limited to 'package/l2tpd/patches/03-jacco-pty.patch')
-rw-r--r-- | package/l2tpd/patches/03-jacco-pty.patch | 1194 |
1 files changed, 0 insertions, 1194 deletions
diff --git a/package/l2tpd/patches/03-jacco-pty.patch b/package/l2tpd/patches/03-jacco-pty.patch deleted file mode 100644 index 67169b8ead..0000000000 --- a/package/l2tpd/patches/03-jacco-pty.patch +++ /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; -+} |