+++ /dev/null
-#!/bin/sh
-
-[ -x /usr/sbin/xl2tpd ] || exit 0
-
-[ -n "$INCLUDE_ONLY" ] || {
- . /lib/functions.sh
- . ../netifd-proto.sh
- init_proto "$@"
-}
-
-proto_l2tp_init_config() {
- proto_config_add_string "username"
- proto_config_add_string "password"
- proto_config_add_string "keepalive"
- proto_config_add_string "pppd_options"
- proto_config_add_boolean "ipv6"
- proto_config_add_int "mtu"
- proto_config_add_string "server"
- available=1
- no_device=1
-}
-
-proto_l2tp_setup() {
- local config="$1"
- local iface="$2"
- local optfile="/tmp/l2tp/options.${config}"
-
- local ip serv_addr server
- json_get_var server server && {
- for ip in $(resolveip -t 5 "$server"); do
- ( proto_add_host_dependency "$config" "$ip" )
- serv_addr=1
- done
- }
- [ -n "$serv_addr" ] || {
- echo "Could not resolve server address"
- sleep 5
- proto_setup_failed "$config"
- exit 1
- }
-
- if [ ! -p /var/run/xl2tpd/l2tp-control ]; then
- /etc/init.d/xl2tpd start
- fi
-
- json_get_vars ipv6 demand keepalive username password pppd_options
- [ "$ipv6" = 1 ] || ipv6=""
- if [ "${demand:-0}" -gt 0 ]; then
- demand="precompiled-active-filter /etc/ppp/filter demand idle $demand"
- else
- demand="persist"
- fi
-
- [ -n "$mtu" ] || json_get_var mtu mtu
-
- local interval="${keepalive##*[, ]}"
- [ "$interval" != "$keepalive" ] || interval=5
-
- mkdir -p /tmp/l2tp
-
- echo "${keepalive:+lcp-echo-interval $interval lcp-echo-failure ${keepalive%%[, ]*}}" > "${optfile}"
- echo "usepeerdns" >> "${optfile}"
- echo "nodefaultroute" >> "${optfile}"
- echo "${username:+user \"$username\" password \"$password\"}" >> "${optfile}"
- echo "ipparam \"$config\"" >> "${optfile}"
- echo "ifname \"l2tp-$config\"" >> "${optfile}"
- echo "ip-up-script /lib/netifd/ppp-up" >> "${optfile}"
- echo "ipv6-up-script /lib/netifd/ppp-up" >> "${optfile}"
- echo "ip-down-script /lib/netifd/ppp-down" >> "${optfile}"
- echo "ipv6-down-script /lib/netifd/ppp-down" >> "${optfile}"
- # Don't wait for LCP term responses; exit immediately when killed.
- echo "lcp-max-terminate 0" >> "${optfile}"
- echo "${ipv6:++ipv6} ${pppd_options}" >> "${optfile}"
- echo "${mtu:+mtu $mtu mru $mtu}" >> "${optfile}"
-
- xl2tpd-control add l2tp-${config} pppoptfile=${optfile} lns=${server} redial=yes redial timeout=20
- xl2tpd-control connect l2tp-${config}
-}
-
-proto_l2tp_teardown() {
- local interface="$1"
- local optfile="/tmp/l2tp/options.${interface}"
-
- case "$ERROR" in
- 11|19)
- proto_notify_error "$interface" AUTH_FAILED
- proto_block_restart "$interface"
- ;;
- 2)
- proto_notify_error "$interface" INVALID_OPTIONS
- proto_block_restart "$interface"
- ;;
- esac
-
- xl2tpd-control disconnect l2tp-${interface}
- # Wait for interface to go down
- while [ -d /sys/class/net/l2tp-${interface} ]; do
- sleep 1
- done
-
- xl2tpd-control remove l2tp-${interface}
- rm -f ${optfile}
-}
-
-[ -n "$INCLUDE_ONLY" ] || {
- add_protocol l2tp
-}
+++ /dev/null
-;
-; Sample l2tpd configuration file
-;
-; This example file should give you some idea of how the options for l2tpd
-; should work. The best place to look for a list of all options is in
-; the source code itself, until I have the time to write better documetation :)
-; Specifically, the file "file.c" contains a list of commands at the end.
-;
-; You most definitely don't have to spell out everything as it is done here
-;
-; [global] ; Global parameters:
-; port = 1701 ; * Bind to port 1701
-; auth file = /etc/xl2tpd/xl2tp-secrets ; * Where our challenge secrets are
-; access control = yes ; * Refuse connections without IP match
-; rand source = dev ; Source for entropy for random
-; ; numbers, options are:
-; ; dev - reads of /dev/urandom
-; ; sys - uses rand()
-; ; egd - reads from egd socket
-; ; egd is not yet implemented
-;
-; [lns default] ; Our fallthrough LNS definition
-; exclusive = no ; * Only permit one tunnel per host
-; ip range = 192.168.0.1-192.168.0.20 ; * Allocate from this IP range
-; no ip range = 192.168.0.3-192.168.0.9 ; * Except these hosts
-; ip range = 192.168.0.5 ; * But this one is okay
-; ip range = lac1-lac2 ; * And anything from lac1 to lac2's IP
-; lac = 192.168.1.4 - 192.168.1.8 ; * These can connect as LAC's
-; no lac = untrusted.marko.net ; * This guy can't connect
-; hidden bit = no ; * Use hidden AVP's?
-; local ip = 192.168.1.2 ; * Our local IP to use
-; length bit = yes ; * Use length bit in payload?
-; require chap = yes ; * Require CHAP auth. by peer
-; refuse pap = yes ; * Refuse PAP authentication
-; refuse chap = no ; * Refuse CHAP authentication
-; refuse authentication = no ; * Refuse authentication altogether
-; require authentication = yes ; * Require peer to authenticate
-; unix authentication = no ; * Use /etc/passwd for auth.
-; name = myhostname ; * Report this as our hostname
-; ppp debug = no ; * Turn on PPP debugging
-; pppoptfile = /etc/ppp/options.xl2tpd.lns ; * ppp options file
-; call rws = 10 ; * RWS for call (-1 is valid)
-; tunnel rws = 4 ; * RWS for tunnel (must be > 0)
-; flow bit = yes ; * Include sequence numbers
-; challenge = yes ; * Challenge authenticate peer ;
-;
-; [lac marko] ; Example VPN LAC definition
-; lns = lns.marko.net ; * Who is our LNS?
-; lns = lns2.marko.net ; * A backup LNS (not yet used)
-; redial = yes ; * Redial if disconnected?
-; redial timeout = 15 ; * Wait n seconds between redials
-; max redials = 5 ; * Give up after n consecutive failures
-; hidden bit = yes ; * User hidden AVP's?
-; local ip = 192.168.1.1 ; * Force peer to use this IP for us
-; remote ip = 192.168.1.2 ; * Force peer to use this as their IP
-; length bit = no ; * Use length bit in payload?
-; require pap = no ; * Require PAP auth. by peer
-; require chap = yes ; * Require CHAP auth. by peer
-; refuse pap = yes ; * Refuse PAP authentication
-; refuse chap = no ; * Refuse CHAP authentication
-; refuse authentication = no ; * Refuse authentication altogether
-; require authentication = yes ; * Require peer to authenticate
-; name = marko ; * Report this as our hostname
-; ppp debug = no ; * Turn on PPP debugging
-; pppoptfile = /etc/ppp/options.xl2tpd.marko ; * ppp options file for this lac
-; call rws = 10 ; * RWS for call (-1 is valid)
-; tunnel rws = 4 ; * RWS for tunnel (must be > 0)
-; flow bit = yes ; * Include sequence numbers
-; challenge = yes ; * Challenge authenticate peer
-;
-; [lac cisco] ; Another quick LAC
-; lns = cisco.marko.net ; * Required, but can take from default
-; require authentication = yes
+++ /dev/null
---- a/Makefile
-+++ b/Makefile
-@@ -62,8 +62,8 @@ OSFLAGS?= -DLINUX -I$(KERNELSRC)/include
- # are packages seperately (eg kernel-headers on Fedora)
- # Note: 2.6.23+ support still needs some changes in the xl2tpd source
- #
--#OSFLAGS+= -DUSE_KERNEL
--#
-+# Kernel mode fixed by sigwall <fionov@gmail.com>
-+OSFLAGS+= -DUSE_KERNEL
- #
- # Uncomment the next line for FreeBSD
- #
---- a/call.c
-+++ b/call.c
-@@ -680,6 +680,8 @@ struct call *get_call (int tunnel, int c
- st->peer.sin_port = port;
- st->refme = refme;
- st->refhim = refhim;
-+ st->udp_fd = -1;
-+ st->pppox_fd = -1;
- bcopy (&addr, &st->peer.sin_addr, sizeof (addr));
- st->next = tunnels.head;
- tunnels.head = st;
---- a/control.c
-+++ b/control.c
-@@ -596,6 +596,9 @@ int control_finish (struct tunnel *t, st
- if (gconfig.debug_state)
- l2tp_log (LOG_DEBUG, "%s: sending SCCCN\n", __FUNCTION__);
- control_xmit (buf);
-+
-+ connect_pppol2tp(t);
-+
- /* Schedule a HELLO */
- tv.tv_sec = HELLO_DELAY;
- tv.tv_usec = 0;
-@@ -608,6 +611,7 @@ int control_finish (struct tunnel *t, st
- "Connection established to %s, %d. Local: %d, Remote: %d (ref=%u/%u).\n",
- IPADDY (t->peer.sin_addr),
- ntohs (t->peer.sin_port), t->ourtid, t->tid, t->refme, t->refhim);
-+
- if (t->lac)
- {
- /* This is part of a LAC, so we want to go ahead
-@@ -635,6 +639,9 @@ int control_finish (struct tunnel *t, st
- IPADDY (t->peer.sin_addr),
- ntohs (t->peer.sin_port), t->ourtid, t->tid, t->refme, t->refhim,
- t->lns->entname);
-+
-+ connect_pppol2tp(t);
-+
- /* Schedule a HELLO */
- tv.tv_sec = HELLO_DELAY;
- tv.tv_usec = 0;
---- a/l2tp.h
-+++ b/l2tp.h
-@@ -167,6 +167,8 @@ struct tunnel
- int ourrws; /* Receive Window Size */
- int rxspeed; /* Receive bps */
- int txspeed; /* Transmit bps */
-+ int udp_fd; /* UDP fd */
-+ int pppox_fd; /* PPPOX tunnel fd */
- struct call *self;
- struct lns *lns; /* LNS that owns us */
- struct lac *lac; /* LAC that owns us */
-@@ -220,6 +222,7 @@ extern void control_xmit (void *);
- extern int ppd;
- extern int switch_io; /* jz */
- extern int control_fd;
-+extern int connect_pppol2tp(struct tunnel *t);
- extern int start_pppd (struct call *c, struct ppp_opts *);
- extern void magic_lac_dial (void *);
- extern int get_entropy (unsigned char *, int);
---- a/linux/include/linux/if_pppol2tp.h
-+++ b/linux/include/linux/if_pppol2tp.h
-@@ -2,7 +2,7 @@
- * Linux PPP over L2TP (PPPoL2TP) Socket Implementation (RFC 2661)
- *
- * This file supplies definitions required by the PPP over L2TP driver
-- * (pppol2tp.c). All version information wrt this file is located in pppol2tp.c
-+ * (l2tp_ppp.c). All version information wrt this file is located in l2tp_ppp.c
- *
- * License:
- * This program is free software; you can redistribute it and/or
-@@ -15,18 +15,13 @@
- #ifndef __LINUX_IF_PPPOL2TP_H
- #define __LINUX_IF_PPPOL2TP_H
-
--#include <asm/types.h>
--
--#ifdef __KERNEL__
--#include <linux/in.h>
--#endif
-+#include <linux/types.h>
-
- /* Structure used to connect() the socket to a particular tunnel UDP
-- * socket.
-+ * socket over IPv4.
- */
--struct pppol2tp_addr
--{
-- pid_t pid; /* pid that owns the fd.
-+struct pppol2tp_addr {
-+ __kernel_pid_t pid; /* pid that owns the fd.
- * 0 => current */
- int fd; /* FD of UDP socket to use */
-
-@@ -36,6 +31,45 @@ struct pppol2tp_addr
- __u16 d_tunnel, d_session; /* For sending outgoing packets */
- };
-
-+/* Structure used to connect() the socket to a particular tunnel UDP
-+ * socket over IPv6.
-+ */
-+struct pppol2tpin6_addr {
-+ __kernel_pid_t pid; /* pid that owns the fd.
-+ * 0 => current */
-+ int fd; /* FD of UDP socket to use */
-+
-+ __u16 s_tunnel, s_session; /* For matching incoming packets */
-+ __u16 d_tunnel, d_session; /* For sending outgoing packets */
-+
-+ struct sockaddr_in6 addr; /* IP address and port to send to */
-+};
-+
-+/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
-+ * bits. So we need a different sockaddr structure.
-+ */
-+struct pppol2tpv3_addr {
-+ __kernel_pid_t pid; /* pid that owns the fd.
-+ * 0 => current */
-+ int fd; /* FD of UDP or IP socket to use */
-+
-+ struct sockaddr_in addr; /* IP address and port to send to */
-+
-+ __u32 s_tunnel, s_session; /* For matching incoming packets */
-+ __u32 d_tunnel, d_session; /* For sending outgoing packets */
-+};
-+
-+struct pppol2tpv3in6_addr {
-+ __kernel_pid_t pid; /* pid that owns the fd.
-+ * 0 => current */
-+ int fd; /* FD of UDP or IP socket to use */
-+
-+ __u32 s_tunnel, s_session; /* For matching incoming packets */
-+ __u32 d_tunnel, d_session; /* For sending outgoing packets */
-+
-+ struct sockaddr_in6 addr; /* IP address and port to send to */
-+};
-+
- /* Socket options:
- * DEBUG - bitmask of debug message categories
- * SENDSEQ - 0 => don't send packets with sequence numbers
-@@ -66,4 +100,4 @@ enum {
-
-
-
--#endif
-+#endif /* __LINUX_IF_PPPOL2TP_H */
---- a/network.c
-+++ b/network.c
-@@ -45,6 +45,7 @@ int init_network (void)
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = gconfig.listenaddr;
- server.sin_port = htons (gconfig.port);
-+ int flags;
- if ((server_socket = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
- {
- l2tp_log (LOG_CRIT, "%s: Unable to allocate socket. Terminating.\n",
-@@ -52,6 +53,10 @@ int init_network (void)
- return -EINVAL;
- };
-
-+ flags = 1;
-+ setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
-+ setsockopt(server_socket, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));
-+
- if (bind (server_socket, (struct sockaddr *) &server, sizeof (server)))
- {
- close (server_socket);
-@@ -321,6 +326,11 @@ int build_fdset (fd_set *readfds)
-
- while (tun)
- {
-+ if (tun->udp_fd > -1) {
-+ if (tun->udp_fd > max)
-+ max = tun->udp_fd;
-+ FD_SET (tun->udp_fd, readfds);
-+ }
- call = tun->call_head;
- while (call)
- {
-@@ -390,6 +400,8 @@ void network_thread ()
- struct iovec iov;
- char cbuf[256];
- unsigned int refme, refhim;
-+ int * currentfd;
-+ int server_socket_processed;
-
- /* This one buffer can be recycled for everything except control packets */
- buf = new_buf (MAX_RECV_SIZE);
-@@ -428,7 +440,21 @@ void network_thread ()
- {
- do_control ();
- }
-- if (FD_ISSET (server_socket, &readfds))
-+ server_socket_processed = 0;
-+ currentfd = NULL;
-+ st = tunnels.head;
-+ while (st || !server_socket_processed) {
-+ if (st && (st->udp_fd == -1)) {
-+ st=st->next;
-+ continue;
-+ }
-+ if (st) {
-+ currentfd = &st->udp_fd;
-+ } else {
-+ currentfd = &server_socket;
-+ server_socket_processed = 1;
-+ }
-+ if (FD_ISSET (*currentfd, &readfds))
- {
- /*
- * Okay, now we're ready for reading and processing new data.
-@@ -457,12 +483,19 @@ void network_thread ()
- msgh.msg_flags = 0;
-
- /* Receive one packet. */
-- recvsize = recvmsg(server_socket, &msgh, 0);
-+ recvsize = recvmsg(*currentfd, &msgh, 0);
-
- if (recvsize < MIN_PAYLOAD_HDR_LEN)
- {
- if (recvsize < 0)
- {
-+ if (errno == ECONNREFUSED) {
-+ close(*currentfd);
-+ }
-+ if ((errno == ECONNREFUSED) ||
-+ (errno == EBADF)) {
-+ *currentfd = -1;
-+ }
- if (errno != EAGAIN)
- l2tp_log (LOG_WARNING,
- "%s: recvfrom returned error %d (%s)\n",
-@@ -567,6 +600,8 @@ void network_thread ()
- }
- };
- }
-+ if (st) st=st->next;
-+ }
-
- /*
- * finished obvious sources, look for data from PPP connections.
-@@ -639,3 +674,82 @@ void network_thread ()
- }
-
- }
-+
-+int connect_pppol2tp(struct tunnel *t) {
-+#ifdef USE_KERNEL
-+ if (kernel_support) {
-+ int ufd = -1, fd2 = -1;
-+ int flags;
-+ struct sockaddr_pppol2tp sax;
-+
-+ struct sockaddr_in server;
-+ server.sin_family = AF_INET;
-+ server.sin_addr.s_addr = gconfig.listenaddr;
-+ server.sin_port = htons (gconfig.port);
-+ if ((ufd = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
-+ {
-+ l2tp_log (LOG_CRIT, "%s: Unable to allocate UDP socket. Terminating.\n",
-+ __FUNCTION__);
-+ return -EINVAL;
-+ };
-+
-+ flags=1;
-+ setsockopt(ufd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
-+ setsockopt(ufd, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));
-+
-+ if (bind (ufd, (struct sockaddr *) &server, sizeof (server)))
-+ {
-+ close (ufd);
-+ l2tp_log (LOG_CRIT, "%s: Unable to bind UDP socket: %s. Terminating.\n",
-+ __FUNCTION__, strerror(errno), errno);
-+ return -EINVAL;
-+ };
-+ server = t->peer;
-+ flags = fcntl(ufd, F_GETFL);
-+ if (flags == -1 || fcntl(ufd, F_SETFL, flags | O_NONBLOCK) == -1) {
-+ l2tp_log (LOG_WARNING, "%s: Unable to set UDP socket nonblock.\n",
-+ __FUNCTION__);
-+ return -EINVAL;
-+ }
-+ if (connect (ufd, (struct sockaddr *) &server, sizeof(server)) < 0) {
-+ l2tp_log (LOG_CRIT, "%s: Unable to connect UDP peer. Terminating.\n",
-+ __FUNCTION__);
-+ return -EINVAL;
-+ }
-+
-+ t->udp_fd=ufd;
-+
-+ fd2 = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
-+ if (fd2 < 0) {
-+ l2tp_log (LOG_WARNING, "%s: Unable to allocate PPPoL2TP socket.\n",
-+ __FUNCTION__);
-+ return -EINVAL;
-+ }
-+ flags = fcntl(fd2, F_GETFL);
-+ if (flags == -1 || fcntl(fd2, F_SETFL, flags | O_NONBLOCK) == -1) {
-+ l2tp_log (LOG_WARNING, "%s: Unable to set PPPoL2TP socket nonblock.\n",
-+ __FUNCTION__);
-+ return -EINVAL;
-+ }
-+ sax.sa_family = AF_PPPOX;
-+ sax.sa_protocol = PX_PROTO_OL2TP;
-+ sax.pppol2tp.pid = 0;
-+ sax.pppol2tp.fd = t->udp_fd;
-+ sax.pppol2tp.addr.sin_addr.s_addr = t->peer.sin_addr.s_addr;
-+ sax.pppol2tp.addr.sin_port = t->peer.sin_port;
-+ sax.pppol2tp.addr.sin_family = AF_INET;
-+ sax.pppol2tp.s_tunnel = t->ourtid;
-+ sax.pppol2tp.s_session = 0;
-+ sax.pppol2tp.d_tunnel = t->tid;
-+ sax.pppol2tp.d_session = 0;
-+ if ((connect(fd2, (struct sockaddr *)&sax, sizeof(sax))) < 0) {
-+ l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket. %d %s\n",
-+ __FUNCTION__, errno, strerror(errno));
-+ close(fd2);
-+ return -EINVAL;
-+ }
-+ t->pppox_fd = fd2;
-+ }
-+#endif
-+ return 0;
-+}
---- a/xl2tpd.c
-+++ b/xl2tpd.c
-@@ -278,7 +278,11 @@ void death_handler (int signal)
- struct tunnel *st, *st2;
- int sec;
- l2tp_log (LOG_CRIT, "%s: Fatal signal %d received\n", __FUNCTION__, signal);
-+#ifdef USE_KERNEL
-+ if (kernel_support || signal != SIGTERM) {
-+#else
- if (signal != SIGTERM) {
-+#endif
- st = tunnels.head;
- while (st)
- {
-@@ -349,7 +353,7 @@ int start_pppd (struct call *c, struct p
- int flags;
- #endif
- int pos = 1;
-- int fd2;
-+ int fd2 = -1;
- #ifdef DEBUG_PPPD
- int x;
- #endif
-@@ -397,7 +401,7 @@ int start_pppd (struct call *c, struct p
- sax.sa_family = AF_PPPOX;
- sax.sa_protocol = PX_PROTO_OL2TP;
- sax.pppol2tp.pid = 0;
-- sax.pppol2tp.fd = server_socket;
-+ sax.pppol2tp.fd = c->container->udp_fd;
- sax.pppol2tp.addr.sin_addr.s_addr = c->container->peer.sin_addr.s_addr;
- sax.pppol2tp.addr.sin_port = c->container->peer.sin_port;
- sax.pppol2tp.addr.sin_family = AF_INET;
-@@ -408,6 +412,7 @@ int start_pppd (struct call *c, struct p
- if (connect(fd2, (struct sockaddr *)&sax, sizeof(sax)) < 0) {
- l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket.\n",
- __FUNCTION__);
-+ close(fd2);
- return -EINVAL;
- }
- stropt[pos++] = strdup ("plugin");
-@@ -484,7 +489,7 @@ int start_pppd (struct call *c, struct p
- dup2 (fd2, 0);
- dup2 (fd2, 1);
- close(fd2);
--
-+ }
- /* close all the calls pty fds */
- st = tunnels.head;
- while (st)
-@@ -492,12 +497,17 @@ int start_pppd (struct call *c, struct p
- sc = st->call_head;
- while (sc)
- {
-- close (sc->fd);
-+#ifdef USE_KERNEL
-+ if (kernel_support) {
-+ close(st->udp_fd); /* tunnel UDP fd */
-+ close(st->pppox_fd); /* tunnel PPPoX fd */
-+ } else
-+#endif
-+ close (sc->fd); /* call pty fd */
- sc = sc->next;
- }
- st = st->next;
- }
-- }
-
- /* close the UDP socket fd */
- close (server_socket);
-@@ -615,6 +625,10 @@ void destroy_tunnel (struct tunnel *t)
- the memory pointed to by t->chal_us.vector at some other place */
- if (t->chal_them.vector)
- free (t->chal_them.vector);
-+ if (t->pppox_fd > -1 )
-+ close (t->pppox_fd);
-+ if (t->udp_fd > -1 )
-+ close (t->udp_fd);
- free (t);
- free (me);
- }