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