Add dedicated option to activate kernel L2TP acceleration via
the pipex(4). The options should be passed by a L2TP tunnel
management daemon (e.g. xl2tpd).
This diff is complete, but kernel support in ppp(4) is not ready.
---
usr.sbin/pppd/ipcp.c | 5 +++
usr.sbin/pppd/options.c | 82 +++++++++++++++++++++++++++++++++++++++++
usr.sbin/pppd/pppd.8 | 18 +++++++++
usr.sbin/pppd/pppd.h | 7 ++++
usr.sbin/pppd/sys-bsd.c | 56 ++++++++++++++++++++++++++++
5 files changed, 168 insertions(+)
diff --git usr.sbin/pppd/ipcp.c usr.sbin/pppd/ipcp.c
index 1296d897b14..e7a6dbd6ee7 100644
--- usr.sbin/pppd/ipcp.c
+++ usr.sbin/pppd/ipcp.c
@@ -1251,6 +1251,10 @@ ipcp_up(f)
return;
}
+ /* enable pipex(4), keep working if failed */
+ if (pipex_conf.pr_protocol && !apipex(go->ouraddr, ho->hisaddr, mask))
+ IPCPDEBUG((LOG_WARNING, "apipex failed"));
+
#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
@@ -1304,6 +1308,7 @@ ipcp_down(f)
if (demand) {
sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
} else {
+ dpipex();
sifdown(f->unit);
ipcp_clear_addrs(f->unit);
}
diff --git usr.sbin/pppd/options.c usr.sbin/pppd/options.c
index 828f7cdce65..fe0e2e6b54b 100644
--- usr.sbin/pppd/options.c
+++ usr.sbin/pppd/options.c
@@ -144,6 +144,9 @@ struct bpf_program pass_filter;/* Filter program for
packets to pass */
struct bpf_program active_filter; /* Filter program for link-active pkts */
pcap_t pc; /* Fake struct pcap so we can compile expr */
#endif
+struct pipex_session_req pipex_conf = { /* pipex(4) session
configuration */
+ .pr_protocol = 0,
+};
/*
* Prototypes
@@ -253,6 +256,8 @@ static int setactivefilter(char **);
static int setmslanman(char **);
#endif
+static int setpipexl2tp(char **);
+
static int number_option(char *, u_int32_t *, int);
static int int_option(char *, int *);
static int readable(int fd);
@@ -391,6 +396,8 @@ static struct cmd {
{"ms-lanman", 0, setmslanman}, /* Use LanMan psswd when using MS-CHAP
*/
#endif
+ {"pipex-l2tp", 6, setpipexl2tp}, /* set pipex(4) L2TP parameters */
+
{NULL, 0, NULL}
};
@@ -2283,3 +2290,78 @@ setmslanman(argv)
return (1);
}
#endif
+
+static int
+inet_atoss(cp, ss)
+ char *cp;
+ struct sockaddr_storage *ss;
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)ss;
+ char *c, *p;
+ unsigned port;
+
+ if ((c = strchr(cp, ':')) == NULL)
+ return 0;
+ *c = '\0';
+ if (!inet_aton(cp, &sin->sin_addr))
+ return 0;
+ if (!(port = strtoul(c + 1, &p, 10)) || *p != '\0')
+ return 0;
+ sin->sin_port = htons(port);
+ sin->sin_family = AF_INET;
+ ss->ss_len = sizeof(*sin);
+
+ return 1;
+}
+
+static int
+strtou16(str, valp)
+ char *str;
+ uint16_t *valp;
+{
+ char *ptr;
+
+ *valp = strtoul(str, &ptr, 0);
+
+ return *ptr == '\0' ? 1 : 0;
+}
+
+static int
+setpipexl2tp(argv)
+ char **argv;
+{
+ BZERO((char *)&pipex_conf, sizeof(pipex_conf));
+
+ if (!inet_atoss(argv[0], &pipex_conf.pr_local_address)) {
+ option_error("pipex-l2tp: invalid local address of tunnel: %s",
argv[0]);
+ return 0;
+ }
+ if (!inet_atoss(argv[1], &pipex_conf.pr_peer_address)) {
+ option_error("pipex-l2tp: invalid peer address of tunnel: %s", argv[1]);
+ return 0;
+ }
+ if (!strtou16(argv[2], &pipex_conf.pr_proto.l2tp.tunnel_id)) {
+ option_error("pipex-l2tp: invalid local tunnel id: %s", argv[2]);
+ return 0;
+ }
+ if (!strtou16(argv[3], &pipex_conf.pr_proto.l2tp.peer_tunnel_id)) {
+ option_error("pipex-l2tp: invalid peer tunnel id: %s", argv[3]);
+ return 0;
+ }
+ if (!strtou16(argv[4], &pipex_conf.pr_session_id)) {
+ option_error("pipex-l2tp: invalid local call id: %s", argv[4]);
+ return 0;
+ }
+ if (!strtou16(argv[5], &pipex_conf.pr_peer_session_id)) {
+ option_error("pipex-l2tp: invalid peer call id: %s", argv[5]);
+ return 0;
+ }
+
+ /* Indicate address field presense */
+ pipex_conf.pr_ppp_flags = PIPEX_PPP_HAS_ACF;
+
+ /* Finally set the protocol type to implicitly indicate config validity */
+ pipex_conf.pr_protocol = PIPEX_PROTO_L2TP;
+
+ return 1;
+}
diff --git usr.sbin/pppd/pppd.8 usr.sbin/pppd/pppd.8
index 5fba6f1714d..6a7f6e01c09 100644
--- usr.sbin/pppd/pppd.8
+++ usr.sbin/pppd/pppd.8
@@ -829,6 +829,24 @@ option is used.
.It Cm xonxoff
Use software flow control (i.e., XON/XOFF) to control the flow of data on
the serial port.
+.It Cm pipex-l2tp Ar ltunaddr ptunaddr ltunid ptunid lcallid pcallid
+OpenBSD specific. Activate and configure kernel L2TP acceleration. Set
+pipex(4) local tunnel address to
+.Ar ltunaddr ,
+peer tunnel address to
+.Ar ptunaddr ,
+local L2TP tunnel id to
+.Ar ltunid ,
+peer L2TP tunnel id to
+.Ar ptunid ,
+local L2TP call id (local session id in terms of pipex(4)) to
+.Ar lcallid
+and peer L2TP call id (peer session id in terms of pipex(4)) to
+.Ar pcallid .
+This option should not be specified in the options file. Instead it
+should be passed to
+.Nm pppd
+by a L2TP daemon, that is responsible for L2TP tunnel establishing.
.El
.Sh OPTIONS FILES
Options can be taken from files as well as the command line.
diff --git usr.sbin/pppd/pppd.h usr.sbin/pppd/pppd.h
index 9cd332939a3..27ddc45bd78 100644
--- usr.sbin/pppd/pppd.h
+++ usr.sbin/pppd/pppd.h
@@ -51,7 +51,10 @@
#include <sys/types.h> /* for u_int32_t, if defined */
#include <sys/time.h> /* for struct timeval */
+#include <netinet/in.h>
#include <net/ppp_defs.h>
+#include <net/if.h>
+#include <net/pipex.h>
#include <stdio.h> /* for FILE */
#include <stdarg.h>
@@ -128,6 +131,7 @@ extern int refuse_chap; /* Don't wanna auth. ourselves
with CHAP */
extern struct bpf_program pass_filter; /* Filter for pkts to pass */
extern struct bpf_program active_filter; /* Filter for link-active pkts */
#endif
+extern struct pipex_session_req pipex_conf; /* pipex(4) session configuration
*/
#ifdef MSLANMAN
extern int ms_lanman; /* Nonzero if use LanMan password instead of NT
*/
@@ -306,6 +310,9 @@ int cifproxyarp(int, u_int32_t);
u_int32_t GetMask(u_int32_t); /* Get appropriate netmask for address */
int lock(char *); /* Create lock file for device */
void unlock(void); /* Delete previously-created lock file */
+int apipex(u_int32_t, u_int32_t, u_int32_t);
+ /* Add pipex(4) to interface */
+void dpipex(void); /* Delete pipex(4) from interface */
int daemon(int, int); /* Detach us from terminal session */
void logwtmp(const char *, const char *, const char *);
/* Write entry to wtmp file */
diff --git usr.sbin/pppd/sys-bsd.c usr.sbin/pppd/sys-bsd.c
index e8deee6d2ff..085888cf06f 100644
--- usr.sbin/pppd/sys-bsd.c
+++ usr.sbin/pppd/sys-bsd.c
@@ -801,6 +801,15 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
quit();
}
+ /* Update pipex(4) config */
+ if (pcomp)
+ pipex_conf.pr_ppp_flags |= PIPEX_PPP_PFC_ACCEPTED;
+ else
+ pipex_conf.pr_ppp_flags &= ~PIPEX_PPP_PFC_ACCEPTED;
+ if (accomp)
+ pipex_conf.pr_ppp_flags |= PIPEX_PPP_ACFC_ACCEPTED;
+ else
+ pipex_conf.pr_ppp_flags &= ~PIPEX_PPP_ACFC_ACCEPTED;
}
/*
@@ -1510,3 +1519,50 @@ unlock()
lock_file = NULL;
}
}
+
+/*
+ * apipex - enable pipex(4) and add session
+ */
+int
+apipex(o, h, m)
+ u_int32_t o, h, m;
+{
+ int mode = 1;
+
+ if (ioctl(ttyfd, PIPEXSMODE, &mode) == -1) {
+ syslog(LOG_WARNING, "Couldn't enable pipex: %m");
+ return -1;
+ }
+
+ /* Complete session creation request */
+ pipex_conf.pr_ip_srcaddr.s_addr = o;
+ pipex_conf.pr_ip_address.s_addr = h;
+ pipex_conf.pr_ip_netmask.s_addr = m;
+
+ if (ioctl(ttyfd, PIPEXASESSION, &pipex_conf) == -1) {
+ syslog(LOG_WARNING, "Couldn't add pipex session: %m");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * dpipex - del session and disable pipex(4)
+ */
+void
+dpipex()
+{
+ struct pipex_session_close_req cr;
+ int mode = 0;
+
+ /* Copy required data from the session addition request */
+ cr.psr_protocol = pipex_conf.pr_protocol;
+ cr.psr_session_id = pipex_conf.pr_session_id;
+
+ if (ioctl(ttyfd, PIPEXDSESSION, &cr) == -1)
+ syslog(LOG_WARNING, "Couldn't del pipex session: %m");
+
+ if (ioctl(ttyfd, PIPEXSMODE, &mode) == -1)
+ syslog(LOG_WARNING, "Couldn't disable pipex: %m");
+}
--
2.26.0