From c73b62ee6c2b18e498a2febb048d952264c0bc3d Mon Sep 17 00:00:00 2001 From: Paul Wouters Date: Fri, 15 Jun 2012 16:27:04 -0400 Subject: [PATCH] * Fri Jun 15 2012 Paul Wouters - 1.3.1-7 - Moved modprobe code from daemon to initscript/systemd (SElinux does not allow a daemon to do this, see rhbz#832149) --- xl2tpd-1.3.1-kernelmode.patch | 362 ++++++++++++++++++++++++++++++++++ xl2tpd.init | 6 + xl2tpd.service | 2 + xl2tpd.spec | 8 +- 4 files changed, 376 insertions(+), 2 deletions(-) create mode 100644 xl2tpd-1.3.1-kernelmode.patch diff --git a/xl2tpd-1.3.1-kernelmode.patch b/xl2tpd-1.3.1-kernelmode.patch new file mode 100644 index 0000000..34c2e09 --- /dev/null +++ b/xl2tpd-1.3.1-kernelmode.patch @@ -0,0 +1,362 @@ +diff -Naur xl2tpd-1.3.1-orig/call.c xl2tpd-1.3.1/call.c +--- xl2tpd-1.3.1-orig/call.c 2011-10-06 15:22:05.000000000 -0400 ++++ xl2tpd-1.3.1/call.c 2012-06-15 15:57:17.250953288 -0400 +@@ -680,6 +680,8 @@ + 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; +diff -Naur xl2tpd-1.3.1-orig/control.c xl2tpd-1.3.1/control.c +--- xl2tpd-1.3.1-orig/control.c 2012-06-15 15:56:30.169585604 -0400 ++++ xl2tpd-1.3.1/control.c 2012-06-15 15:57:17.251953296 -0400 +@@ -596,6 +596,9 @@ + 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 @@ + "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 @@ + 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; +diff -Naur xl2tpd-1.3.1-orig/l2tp.h xl2tpd-1.3.1/l2tp.h +--- xl2tpd-1.3.1-orig/l2tp.h 2011-10-06 15:22:05.000000000 -0400 ++++ xl2tpd-1.3.1/l2tp.h 2012-06-15 15:57:17.251953296 -0400 +@@ -167,6 +167,8 @@ + 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 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); +diff -Naur xl2tpd-1.3.1-orig/Makefile xl2tpd-1.3.1/Makefile +--- xl2tpd-1.3.1-orig/Makefile 2011-10-06 15:22:05.000000000 -0400 ++++ xl2tpd-1.3.1/Makefile 2012-06-15 15:57:17.250953288 -0400 +@@ -62,8 +62,8 @@ + # 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 ++OSFLAGS+= -DUSE_KERNEL + # + # Uncomment the next line for FreeBSD + # +diff -Naur xl2tpd-1.3.1-orig/network.c xl2tpd-1.3.1/network.c +--- xl2tpd-1.3.1-orig/network.c 2012-06-15 15:56:30.169585604 -0400 ++++ xl2tpd-1.3.1/network.c 2012-06-15 16:00:26.259429931 -0400 +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #ifndef LINUX + # include + #endif +@@ -36,7 +37,6 @@ + int kernel_support; /* Kernel Support there or not? */ + #endif + +- + int init_network (void) + { + long arg; +@@ -45,6 +45,7 @@ + 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 @@ + 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); +@@ -94,7 +99,7 @@ + int kernel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); + if (kernel_fd < 0) + { +- l2tp_log (LOG_INFO, "L2TP kernel support not detected.\n"); ++ l2tp_log (LOG_INFO, "L2TP kernel support not detected (try modprobing l2tp_ppp and pppol2tp)\n"); + kernel_support = 0; + } + else +@@ -321,6 +326,11 @@ + + 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 @@ + 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 @@ + { + 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. +@@ -456,12 +482,19 @@ + 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", +@@ -566,6 +599,8 @@ + } + }; + } ++ if (st) st=st->next; ++ } + + /* + * finished obvious sources, look for data from PPP connections. +@@ -638,3 +673,82 @@ + } + + } ++ ++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; ++} +diff -Naur xl2tpd-1.3.1-orig/xl2tpd.c xl2tpd-1.3.1/xl2tpd.c +--- xl2tpd-1.3.1-orig/xl2tpd.c 2011-10-06 15:22:05.000000000 -0400 ++++ xl2tpd-1.3.1/xl2tpd.c 2012-06-15 15:57:25.189015286 -0400 +@@ -278,7 +278,11 @@ + 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 flags; + #endif + int pos = 1; +- int fd2; ++ int fd2 = -1; + #ifdef DEBUG_PPPD + int x; + #endif +@@ -397,7 +401,7 @@ + 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 @@ + 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 @@ + dup2 (fd2, 0); + dup2 (fd2, 1); + close(fd2); +- ++ } + /* close all the calls pty fds */ + st = tunnels.head; + while (st) +@@ -492,12 +497,17 @@ + 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 @@ + 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); + } diff --git a/xl2tpd.init b/xl2tpd.init index e0494e3..8f20b9d 100644 --- a/xl2tpd.init +++ b/xl2tpd.init @@ -39,6 +39,12 @@ RETVAL=0 start() { echo -n "Starting $SERVICE: " + + # Look for the L2TP kernel handler module, load when needed + if [ ! -d /sys/module/l2tp_ppp ]; then modprobe l2tp_ppp + # if still not found, try legacy one + if [ ! -d /sys/module/l2tp_ppp ]; then modprobe pppol2tp + if [ ! -d /var/run/xl2tpd ] then mkdir /var/run/xl2tpd diff --git a/xl2tpd.service b/xl2tpd.service index b17a447..d222874 100644 --- a/xl2tpd.service +++ b/xl2tpd.service @@ -7,7 +7,9 @@ Wants=openswan.service [Service] Type=simple PIDFile=/var/run/xl2tpd/xl2tpd.pid +ExecStartPre=/sbin/modprobe -q l2tp_ppp ExecStart=/usr/sbin/xl2tpd -D +Restart=on-abort [Install] WantedBy=multi-user.target diff --git a/xl2tpd.spec b/xl2tpd.spec index d0b360f..60672d9 100644 --- a/xl2tpd.spec +++ b/xl2tpd.spec @@ -1,7 +1,7 @@ Summary: Layer 2 Tunnelling Protocol Daemon (RFC 2661) Name: xl2tpd Version: 1.3.1 -Release: 6%{?dist} +Release: 7%{?dist} License: GPL+ Url: http://www.xelerance.com/software/xl2tpd/ Group: System Environment/Daemons @@ -10,7 +10,7 @@ Source1: xl2tpd.service Source2: tmpfiles-xl2tpd.conf Patch1: xl2tpd-1.3.1-Wunused.patch Patch2: xl2tpd-bz80693.patch -Patch3: xl2tpd-1.3.0-kernelmode.patch +Patch3: xl2tpd-1.3.1-kernelmode.patch Patch4: xl2tpd-1.3.1-conf.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: ppp >= 2.4.5-18 @@ -118,6 +118,10 @@ fi %ghost %attr(0600,root,root) %{_localstatedir}/run/xl2tpd/l2tp-control %changelog +* Fri Jun 15 2012 Paul Wouters - 1.3.1-7 +- Moved modprobe code from daemon to initscript/systemd + (SElinux does not allow a daemon to do this, see rhbz#832149) + * Tue Jun 12 2012 Paul Wouters - 1.3.1-6 - Added patch for xl2tpd.conf to improve interop settings (no longer need to say "no encryption" on Windows)