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

Reply via email to