[PATCH] introduce VRFs
David Lamparter <equinox <at> diac24.net>
2011-05-18 15:18:07 GMT
this adds support for VRFs (Virtual Routing and Forwarding
instances) through libvrf from vrf-tools. pptpd gains the ability
to have its TCP and GRE sockets in a VRF different from the one
the process is running in.
As pppd is started from pptpd and does not have VRF support, the
pppX devices will be in the initial VRF. The PPTP traffic will
however be flowing in the given VRF. This allows full separation
of encapsulated and encapsulating networks.
Signed-off-by: David Lamparter <david.lamparter <at> adyton.net>
Cc: David Lamparter <equinox <at> diac24.net>
Cc: Franco Fichtner <franco.fichtner <at> adyton.net>
--
Attached code is put into public domain affirmed by both me
(David Lamparter, the author) as well as my employer (Adyton
Systems AG) who paid for it to be written. Assigning copyright
to the FSF is impossible under German law.
--
David Lamparter | Software Developer | Adyton Systems AG
Mozartstr. 3 | 04107 Leipzig | Germany
phone +49 341.39 299 343 | fax +49 341.39 299 343-9
trade register: Amtsgericht Leipzig HRB26578
---
AUTHORS | 1 +
ChangeLog | 14 ++++++++++++++
NEWS | 1 +
README.vrf | 21 +++++++++++++++++++++
configure.in | 49 +++++++++++++++++++++++++++++++++++++++++++++----
defaults.h | 1 +
pptpctrl.c | 17 ++++++++++++++++-
pptpctrl.h | 6 ++++++
pptpd.c | 43 +++++++++++++++++++++++++++++++++----------
pptpgre.c | 5 ++++-
pptpmanager.c | 9 ++++++++-
samples/pptpd.conf | 6 ++++++
pptpd.8 | 4 ++++
pptpd.conf.5 | 6 ++++++
14 files changed, 166 insertions(+), 17 deletions(-)
create mode 100644 README.vrf
diff --git a/AUTHORS b/AUTHORS
index 3fd1e89..1e42535 100644
--- a/AUTHORS
+++ b/AUTHORS
<at> <at> -29,6 +29,7 <at> <at> Chris Wilson
Anton Gorlov
Charlie Brady
Michael Douglass <mikedoug at mikedoug dot net>
+David Lamparter <equinox at diac24 dot net>
The Linux PPTP Server takes advantage of some Linux PPTP client code
written by C. Scott Ananian <cananian at alumni.princeton.edu>
diff --git a/ChangeLog b/ChangeLog
index 971e8ec..a73179d 100644
--- a/ChangeLog
+++ b/ChangeLog
<at> <at> -1,3 +1,17 <at> <at>
+Wed May 18 14:42:28 2011 David Lamparter <david.lamparter <at> adyton.net>
+
+ * pptpctrl.c, pptpd.c, pptpgre.c, pptpmanager.c: introduce VRFs
+
+ this adds support for VRFs (Virtual Routing and Forwarding
+ instances) through libvrf from vrf-tools. pptpd gains the ability
+ to have its TCP and GRE sockets in a VRF different from the one
+ the process is running in.
+
+ As pppd is started from pptpd and does not have VRF support, the
+ pppX devices will be in the initial VRF. The PPTP traffic will
+ however be flowing in the given VRF. This allows full separation
+ of encapsulated and encapsulating networks.
+
Mon Jun 15 12:53:58 2009 Michael Douglass <mikedoug <at> mikedoug.net>
* pptpctrl.c (pptp_handle_ctrl_connection): fix IDLE_WAIT
diff --git a/NEWS b/NEWS
index 4b468a7..c736f68 100644
--- a/NEWS
+++ b/NEWS
<at> <at> -1,3 +1,4 <at> <at>
+- add support for VRFs through libvrf [Lamparter]
- fix implementation of IDLE_WAIT [Douglass]
- fix compilation with uclibc with legacy support disabled [Hiramoto]
- avoid ipparam and logwtmp on BSD [Cameron]
diff --git a/README.vrf b/README.vrf
new file mode 100644
index 0000000..9fee082
--- /dev/null
+++ b/README.vrf
<at> <at> -0,0 +1,21 <at> <at>
+VRF HOWTO for pptpd-1.3.X
+
+1) Grab vrf-tools from
+ http://git.spaceboyz.net/equinox/vrf-tools.git/
+ (use newest available)
+
+2) Install vrf-tools
+
+3) Install pptpd:
+ ./configure --enable-vrf
+
+ if the configuration script cannot find the header
+ and/or library, try adjusting CFLAGS and/or LDFLAGS.
+
+4) Set up pptpd to run in the VRF that shall terminate
+ the tunnels. Specify the VRF that shall have the listening
+ sockets with the "vrf" option or the "--vrf" parameter.
+
+David Lamparter, equinox at diac24 dot net
+Wed May 18 14:42:28 2011
+
diff --git a/configure.in b/configure.in
index 30f5145..d914b87 100644
--- a/configure.in
+++ b/configure.in
<at> <at> -86,6 +86,26 <at> <at> AC_ARG_ENABLE(bcrelay,
esac
], [AC_MSG_RESULT(default no)])
+AC_MSG_CHECKING(command line for VRF build)
+AC_ARG_ENABLE(vrf,
+ [ --enable-vrf Enable support for VRFs],
+ [
+ case "$enableval" in
+ yes)
+ AC_MSG_RESULT(yes)
+ VRF=$enableval
+ ;;
+ no)
+ AC_MSG_RESULT(explicit no)
+ ;;
+ *)
+ AC_MSG_RESULT(unrecognised... terminating)
+ exit 1
+ ;;
+ esac
+ ], [AC_MSG_RESULT(default no)])
+
+
AC_PROG_CC
AC_PROG_RANLIB
AC_PROG_INSTALL
<at> <at> -207,10 +227,6 <at> <at> if test "$ac_cv_header_libintl_h" = yes; then
fi
fi
-AC_SUBST(XTRALIBS_CTRL)
-AC_SUBST(XTRALIBS_MGR)
-AC_SUBST(HAVE_OPENPTY)
-
if test "$BCRELAY" = "yes"; then
if test "$BCRELAY" = "yes"; then
XTRA_PROG="bcrelay"
<at> <at> -220,7 +236,25 <at> <at> if test "$BCRELAY" = "yes"; then
fi
fi
+if test "$VRF" = "yes"; then
+ AC_CHECKING([for vrf Library and Header files])
+ AC_CHECK_HEADER(vrf.h, ,
+ AC_MSG_ERROR([vrf headers were not found])
+ )
+
+ AC_CHECK_LIB(vrf, vrf_socket, [
+ AC_DEFINE(VRF, 1, [Use vrf_socket from vrf library])
+ XTRALIBS_CTRL="$XTRALIBS_CTRL -lvrf"
+ XTRALIBS_MGR="$XTRALIBS_MGR -lvrf"
+ ], [
+ AC_MSG_ERROR(vrf library was not found)
+ ])
+fi
+
+AC_SUBST(XTRALIBS_CTRL)
+AC_SUBST(XTRALIBS_MGR)
AC_SUBST(XTRA_PROG)
+AC_SUBST(HAVE_OPENPTY)
echo '==============================================================================='
<at> <at> -251,5 +285,12 <at> <at> else
echo 'No.'
fi
+echo -n ' VRF support: '
+if test "$VRF" = "yes"; then
+ echo 'Yes.'
+else
+ echo 'No.'
+fi
+
AC_CACHE_SAVE
AC_OUTPUT(Makefile)
diff --git a/defaults.h b/defaults.h
index 0b4e414..99fd58c 100644
--- a/defaults.h
+++ b/defaults.h
<at> <at> -67,6 +67,7 <at> <at>
#define LOCALIP_KEYWORD "localip"
#define REMOTEIP_KEYWORD "remoteip"
#define LISTEN_KEYWORD "listen"
+#define VRF_KEYWORD "vrf"
#define PIDFILE_KEYWORD "pidfile"
#define STIMEOUT_KEYWORD "stimeout"
#define NOIPPARAM_KEYWORD "noipparam"
diff --git a/pptpctrl.c b/pptpctrl.c
index 0ca026c..7d7a237 100644
--- a/pptpctrl.c
+++ b/pptpctrl.c
<at> <at> -54,6 +54,9 <at> <at>
// placing net/if.h here fixes build on Solaris
#include <net/if.h>
+#ifdef VRF
+char *vrf = NULL;
+#endif
static char *ppp_binary = PPP_BINARY;
static int pptp_logwtmp;
static int noipparam; /* if true, don't send ipparam to ppp */
<at> <at> -135,6 +138,9 <at> <at> int main(int argc, char **argv)
/* note: update pptpctrl.8 if the argument list format is changed */
GETARG_INT(pptpctrl_debug);
GETARG_INT(noipparam);
+#ifdef VRF
+ GETARG_STRING(vrf);
+#endif
GETARG_VALUE(pppdxfig);
GETARG_VALUE(speed);
GETARG_VALUE(pppLocal);
<at> <at> -142,8 +148,17 <at> <at> int main(int argc, char **argv)
if (arg < argc) GETARG_INT(unique_call_id);
if (arg < argc) GETARG_STRING(ppp_binary);
if (arg < argc) GETARG_INT(pptp_logwtmp);
-
+
+#ifdef VRF
+ if (!*vrf) {
+ free(vrf);
+ vrf = NULL;
+ }
+#endif
if (pptpctrl_debug) {
+#ifdef VRF
+ syslog(LOG_DEBUG, "CTRL: VRF used = %s", vrf ? vrf : "NONE");
+#endif
if (*pppLocal)
syslog(LOG_DEBUG, "CTRL: local address = %s", pppLocal);
if (*pppRemote)
diff --git a/pptpctrl.h b/pptpctrl.h
index 9305e74..2043d6d 100644
--- a/pptpctrl.h
+++ b/pptpctrl.h
<at> <at> -11,4 +11,10 <at> <at>
extern int pptpctrl_debug;
+#ifdef VRF
+extern char *vrf;
+#else
+#define vrf_socket(vrf, dom, typ, prot) socket(dom, typ, prot)
+#endif
+
#endif /* !_PPTPD_PPTPCTRL_H */
diff --git a/pptpd.c b/pptpd.c
index ac009e6..432b862 100644
--- a/pptpd.c
+++ b/pptpd.c
<at> <at> -54,6 +54,9 <at> <at> char *ppp_binary = NULL;
char *pppdoptstr = NULL;
char *speedstr = NULL;
char *bindaddr = NULL;
+#ifdef VRF
+char *vrf = NULL;
+#endif
#ifdef BCRELAY
char *bcrelay = NULL;
#endif
<at> <at> -86,8 +89,11 <at> <at> static void showusage(char *prog)
printf("\npptpd v%s\n", VERSION);
printf("Usage: pptpd [options], where options are:\n\n");
#ifdef BCRELAY
+#define OPT_BCRELAY "b"
printf(" [-b] [--bcrelay if] Use broadcast relay for broadcasts comming from.\n");
printf(" the specified interface (default is eth1).\n");
+#else
+#define OPT_BCRELAY ""
#endif
printf(" [-c] [--conf file] Specifies the config file to read default\n");
printf(" settings from (default is %s).\n", PPTPD_CONFIG_FILE_DEFAULT);
<at> <at> -98,6 +104,14 <at> <at> static void showusage(char *prog)
printf(" [-i] [--noipparam] Suppress the passing of the client's IP address\n");
printf(" to PPP, which is done by default otherwise.\n");
printf(" [-l] [--listen x.x.x.x] Specifies IP of local interface to listen to.\n");
+#ifdef VRF
+#define OPT_VRFA "V:"
+#define OPT_VRF "V"
+ printf(" [-V] [--vrf name] Use given VRF for GRE/TCP sockets.\n");
+#else
+#define OPT_VRFA ""
+#define OPT_VRF ""
+#endif
#if !defined(BSDUSER_PPP)
printf(" [-o] [--option file] Specifies the PPP options file to use\n");
printf(" (default is /etc/ppp/options).\n");
<at> <at> -148,11 +162,7 <at> <at> int main(int argc, char **argv)
/* process command line options */
while (1) {
int option_index = 0;
-#ifdef BCRELAY
- char *optstring = "b:c:de:fhil:o:p:s:t:vwC:D";
-#else
- char *optstring = "c:de:fhil:o:p:s:t:vwC:D";
-#endif
+ char *optstring = OPT_BCRELAY ":c:de:fhil:o:p:s:t:vwC:D" OPT_VRFA;
static struct option long_options[] =
{
<at> <at> -174,6 +184,9 <at> <at> int main(int argc, char **argv)
{"logwtmp", 0, 0, 0},
{"connections", 1, 0, 0},
{"delegate", 0, 0, 0},
+#ifdef VRF
+ {"vrf", 1, 0, 0},
+#endif
{0, 0, 0, 0}
};
<at> <at> -182,11 +195,8 <at> <at> int main(int argc, char **argv)
break;
/* convert long options to short form */
if (c == 0)
-#ifdef BCRELAY
- c = "bcdefhilopstvwCD"[option_index];
-#else
- c = "cdefhilopstvwCD"[option_index];
-#endif
+ c = OPT_BCRELAY "cdefhilopstvwCD" OPT_VRF [option_index];
+
switch (c) {
#ifdef BCRELAY
case 'b': /* --bcrelay */
<at> <at> -205,6 +215,13 <at> <at> int main(int argc, char **argv)
bindaddr = strdup(tmpstr);
break;
+#ifdef VRF
+ case 'V': /* --vrf */
+ if (vrf) free(vrf);
+ vrf = strdup(optarg);
+ break;
+#endif
+
case 'h': /* --help */
showusage(argv[0]);
return 0;
<at> <at> -323,6 +340,12 <at> <at> int main(int argc, char **argv)
bindaddr = strdup(tmpstr);
}
+#ifdef VRF
+ if (!vrf && read_config_file(configFile, VRF_KEYWORD, tmp) > 0) {
+ vrf = strdup(tmp);
+ }
+#endif
+
if (!speedstr && read_config_file(configFile, SPEED_KEYWORD, tmp) > 0)
speedstr = strdup(tmp);
diff --git a/pptpgre.c b/pptpgre.c
index 4706cdf..1fa544e 100644
--- a/pptpgre.c
+++ b/pptpgre.c
<at> <at> -33,6 +33,9 <at> <at>
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
+#ifdef VRF
+#include <vrf.h>
+#endif
#include "ppphdlc.h"
#include "pptpgre.h"
<at> <at> -70,7 +73,7 <at> <at> int pptp_gre_init(u_int32_t call_id_pair, int pty_fd, struct in_addr *inetaddrs)
int gre_fd;
/* Open IP protocol socket */
- gre_fd = socket(AF_INET, SOCK_RAW, PPTP_PROTO);
+ gre_fd = vrf_socket(vrf, AF_INET, SOCK_RAW, PPTP_PROTO);
if (gre_fd < 0) {
syslog(LOG_ERR, "GRE: socket() failed");
return -1;
diff --git a/pptpmanager.c b/pptpmanager.c
index 1363fec..8cfa6d6 100644
--- a/pptpmanager.c
+++ b/pptpmanager.c
<at> <at> -32,6 +32,9 <at> <at>
#include <time.h>
#include <sys/time.h>
#include <fcntl.h>
+#ifdef VRF
+#include <vrf.h>
+#endif
#if HAVE_LIBWRAP
/* re-include, just in case HAVE_SYSLOG_H wasn't defined */
<at> <at> -413,7 +416,7 <at> <at> static int createHostSocket(int *hostSocket)
#endif
/* create the master socket and check it worked */
- if ((*hostSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0)
+ if ((*hostSocket = vrf_socket(vrf, AF_INET, SOCK_STREAM, 0)) == 0)
return -1;
/* set master socket to allow daemon to be restarted with connections active */
<at> <at> -492,6 +495,10 <at> <at> static void connectCall(int clientSocket, int clientNumber)
ctrl_noipparam[1] = '\0';
ctrl_argv[pptpctrl_argc++] = ctrl_noipparam;
+#ifdef VRF
+ ctrl_argv[pptpctrl_argc++] = vrf ? vrf : "";
+#endif
+
/* optionfile = TRUE or FALSE; so the CTRL manager knows whether to load a non-standard options file */
NUM2ARRAY(pppdoptfile_argv, pppdoptstr ? 1 : 0);
pppdoptfile_argv[1] = '\0';
diff --git a/samples/pptpd.conf b/samples/pptpd.conf
index 4abe15b..ef3a8f6 100644
--- a/samples/pptpd.conf
+++ b/samples/pptpd.conf
<at> <at> -38,6 +38,12 <at> <at> option /etc/ppp/options.pptpd
#
logwtmp
+# TAG: vrf <vrfname>
+# Switches PPTP & GRE sockets to the specified VRF, which must exist
+# Only available if VRF support was compiled into pptpd.
+#
+#vrf test
+
# TAG: bcrelay <if>
# Turns on broadcast relay to clients from interface <if>
#
diff --git a/pptpd.8 b/pptpd.8
index d10b1af..a14c816 100644
--- a/pptpd.8
+++ b/pptpd.8
<at> <at> -117,6 +117,10 <at> <at> With this option, pptpd does not pass an address, and so pppd may use
radius or chap-secrets to allocate an address.
.TP
+\fB-V\fR|\fB--vrf \fIvrf-name
+specifies the VRF to be used for listening in.
+
+.TP
.BR -v | --version
displays the current version of the pptp daemon.
diff --git a/pptpd.conf.5 b/pptpd.conf.5
index c492344..8a3be68 100644
--- a/pptpd.conf.5
+++ b/pptpd.conf.5
<at> <at> -117,6 +117,12 <at> <at> connections (TCP port 1723). Equivalent to the command line
.B --listen
option.
.TP
+.BI "vrf " vrf-name
+VRF to use for the TCP listening socket as well as the GRE
+packets. Equivalent to the command line
+.B --vrf
+option.
+.TP
.BI "pidfile " pid-file
specifies an alternate location to store the process ID file
(default /var/run/pptpd.pid). Equivalent to the command line
--
--
1.7.1
------------------------------------------------------------------------------
What Every C/C++ and Fortran developer Should Know!
Read this article and learn how Intel has extended the reach of its
next-generation tools to help Windows* and Linux* C/C++ and Fortran
developers boost performance applications - including clusters.
http://p.sf.net/sfu/intel-dev2devmay