Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-29 Thread Stuart Henderson
On 2020/05/28 19:42, Jason McIntyre wrote:
> On Wed, May 27, 2020 at 08:43:47AM +0200, Martin Pieuchot wrote:
> > On 26/05/20(Tue) 10:31, Claudio Jeker wrote:
> > > [...] 
> > > npppd(8) is server only it can not establish a connection. pppd(8) on the
> > > other hand is more client side (but I think it can do both).
> > 
> > Could someone knowledgable indicate that in the man pages?
> 
> well, i don;t qualify as knowledgable about ppp, but i'll bite anyway:
> 
> > Currently there is:
> > 
> > npppd ??? new Point-to-Point Protocol daemon
> > pppd ??? Point-to-Point Protocol daemon
> > 
> > Confusing...
> > 
> 
> yes. at the time, i think npppd's description made sense - it was
> a newer version of the ppp server. i think it was pppd that had
> the confusing description, but there was a reason for that too.
> wasn;t there an alternative way to do dialup, and pppd was the
> kernel method?

Here's an overview.

ppp(4), runs PPP in the kernel, controlled by pppd(8). Used for
serial port devices or via a helper application (e.g. xl2tpd in ports
for L2TP client/server - could do PPPoE via a helper too). Client or
server. The version we have is IPv4 only. (Still maintained upstream
but the support for most OS was removed after 2.3.11 in 1999,
it's now Linux/Solaris only).

pppoe(4), runs PPP-over-Ethernet in the kernel using the sppp(4) layer.
Controlled by ifconfig. Client side only. IPv4 and IPv6.

ppp(8), removed in 5.6. Ran PPP in userland and used the tun(4) device
to send packets to/from the kernel. It was used for serial port devices
or PPPoE via a helper (probably also pptp via a helper IIRC). Client
or server. IPv4 and IPv6.

npppd(8), runs L2TP, PPTP, PPPoE. Either userland via tun(4), or hybrid
userland+kernel - userland for connection setup, kernel via pipex(4)
devices handling bulk data transfer after setup. Server side only.
Mostly IPv4 only (L2TP can listen on IPv6 but the PPP sessions
themselves are v4-only).



Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-28 Thread Jason McIntyre
On Wed, May 27, 2020 at 08:43:47AM +0200, Martin Pieuchot wrote:
> On 26/05/20(Tue) 10:31, Claudio Jeker wrote:
> > [...] 
> > npppd(8) is server only it can not establish a connection. pppd(8) on the
> > other hand is more client side (but I think it can do both).
> 
> Could someone knowledgable indicate that in the man pages?

well, i don;t qualify as knowledgable about ppp, but i'll bite anyway:

> Currently there is:
> 
>   npppd ??? new Point-to-Point Protocol daemon
>   pppd ??? Point-to-Point Protocol daemon
> 
> Confusing...
> 

yes. at the time, i think npppd's description made sense - it was
a newer version of the ppp server. i think it was pppd that had
the confusing description, but there was a reason for that too.
wasn;t there an alternative way to do dialup, and pppd was the
kernel method?

i guess i'm going to be burned for that vague text. anyway:

> The DESCRIPTIONs aren't much more helpful :)
> 

to be honest, i think they're clear enough. i do dislike the
descriptions: "new" always goes out of date. i personally don;t
have any suggestions though. if we make them the same, they could cause
more confusion (or just as much). we could make pppd client/daemon, and
remove "new" i suppose:

npppd - Point-to-Point Protocol daemon
pppd - Point-to-Point Protocol client/daemon

jmc



Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-27 Thread Martin Pieuchot
On 26/05/20(Tue) 10:31, Claudio Jeker wrote:
> [...] 
> npppd(8) is server only it can not establish a connection. pppd(8) on the
> other hand is more client side (but I think it can do both).

Could someone knowledgable indicate that in the man pages?  Currently
there is:

npppd – new Point-to-Point Protocol daemon
pppd – Point-to-Point Protocol daemon

Confusing...

The DESCRIPTIONs aren't much more helpful :)



Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-26 Thread Sergey Ryazanov
On Tue, May 26, 2020 at 11:31 AM Claudio Jeker  wrote:
> On Tue, May 26, 2020 at 09:22:28AM +0200, Martin Pieuchot wrote:
> > On 25/05/20(Mon) 21:42, Sergey Ryazanov wrote:
> > > 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).
> >
> > What is the difference between npppd(8) and pppd(8)?   Aren't those two
> > redundant?  Why did you choose to modify pppd(8) and not npppd(8)?
>
> npppd(8) is server only it can not establish a connection. pppd(8) on the
> other hand is more client side (but I think it can do both).

True.

> I think the split in userland makes sense (using npppd as LNS/LAC and pppd
> to connect to a ISP via PPP (even though we also use sppp/pppoe(4) for
> that). Now for the kernel side it would be great if the interface used
> would be the same for all ppp users. In this regard this is a step in the
> right direction.

Comparing addition of client support to npppd and reworking pppd to
support pppx(4), I will choose the npppd reworking. The pppd code is
the mess that is too tightly connected with TTY.

Moreover, pppd is designed to establish the PPP connection over any
type of serial line, including RS232 connected Dial-Up modem. So
introducing the pppx(4) support will require preserving of all
existing code *and* creation of a big module that is responsible
pppx(4) handling in case of L2TP connection. And such feature will
require a hard xl2tpd daemon reworking too. It is easier to rework
npppd or ever create a new L2TP client daemon from the scratch.

So I found a 3rd solution - add a pipex(4) support for the good
old-fashioned ppp(4) and a tiny option for pppd. And this my plan if
someone do not have a better solution.

> > > 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_addr))
> > > +   return 0;
> > > +if (!(port = strtoul(c + 1, , 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, , 0);
> > > +
> > > +return *ptr == '\0' ? 1 : 0;
> > > +}
> > > +
> > > +static int
> > > +setpipexl2tp(argv)
> > > +char **argv;
> > > +{
> > > +BZERO((char *)_conf, 

Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-26 Thread Vitaliy Makkoveev


> On 26 May 2020, at 11:31, Claudio Jeker  wrote:
> 
> [skip]
> 
> Is pppd(8) still using K function declarations? Can we please add new
> functions with ANSI declarations instead and convert the rest as well. 
> Also it looks like something strange is going on with indentation (just
> look at the last function above, it seems lines start with 4 spaces
> instead of 1 tab). Again this could be bad pppd code.

pppd(8) is not KNF compliant.



Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-26 Thread Claudio Jeker
On Tue, May 26, 2020 at 09:22:28AM +0200, Martin Pieuchot wrote:
> On 25/05/20(Mon) 21:42, Sergey Ryazanov wrote:
> > 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).
> 
> What is the difference between npppd(8) and pppd(8)?   Aren't those two
> redundant?  Why did you choose to modify pppd(8) and not npppd(8)?

npppd(8) is server only it can not establish a connection. pppd(8) on the
other hand is more client side (but I think it can do both).

I think the split in userland makes sense (using npppd as LNS/LAC and pppd
to connect to a ISP via PPP (even though we also use sppp/pppoe(4) for
that). Now for the kernel side it would be great if the interface used
would be the same for all ppp users. In this regard this is a step in the
right direction.

 
> > 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_addr))
> > +   return 0;
> > +if (!(port = strtoul(c + 1, , 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, , 0);
> > +
> > +return *ptr == '\0' ? 1 : 0;
> > +}
> > +
> > +static int
> > +setpipexl2tp(argv)
> > +char **argv;
> > +{
> > +BZERO((char *)_conf, sizeof(pipex_conf));
> > +
> > +if (!inet_atoss(argv[0], _conf.pr_local_address)) {
> > +   option_error("pipex-l2tp: invalid local address of tunnel: %s", 
> > argv[0]);
> > +   return 0;
> > +}
> > +if (!inet_atoss(argv[1], _conf.pr_peer_address)) {
> > +   option_error("pipex-l2tp: invalid peer address of tunnel: %s", argv[1]);
> > +   return 0;
> > +}
> > +if (!strtou16(argv[2], _conf.pr_proto.l2tp.tunnel_id)) {
> > +   option_error("pipex-l2tp: invalid local tunnel id: %s", argv[2]);
> > +   return 0;
> > +}
> > +if (!strtou16(argv[3], _conf.pr_proto.l2tp.peer_tunnel_id)) {
> > +   option_error("pipex-l2tp: invalid peer tunnel id: %s", argv[3]);
> > +   return 0;
> > +}
> > +if 

Re: [RFC] pppd: add pipex(4) L2TP control support

2020-05-26 Thread Martin Pieuchot
On 25/05/20(Mon) 21:42, Sergey Ryazanov wrote:
> 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).

What is the difference between npppd(8) and pppd(8)?   Aren't those two
redundant?  Why did you choose to modify pppd(8) and not npppd(8)?

> 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 @@ structbpf_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_addr))
> + return 0;
> +if (!(port = strtoul(c + 1, , 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, , 0);
> +
> +return *ptr == '\0' ? 1 : 0;
> +}
> +
> +static int
> +setpipexl2tp(argv)
> +char **argv;
> +{
> +BZERO((char *)_conf, sizeof(pipex_conf));
> +
> +if (!inet_atoss(argv[0], _conf.pr_local_address)) {
> + option_error("pipex-l2tp: invalid local address of tunnel: %s", 
> argv[0]);
> + return 0;
> +}
> +if (!inet_atoss(argv[1], _conf.pr_peer_address)) {
> + option_error("pipex-l2tp: invalid peer address of tunnel: %s", argv[1]);
> + return 0;
> +}
> +if (!strtou16(argv[2], _conf.pr_proto.l2tp.tunnel_id)) {
> + option_error("pipex-l2tp: invalid local tunnel id: %s", argv[2]);
> + return 0;
> +}
> +if (!strtou16(argv[3], _conf.pr_proto.l2tp.peer_tunnel_id)) {
> + option_error("pipex-l2tp: invalid peer tunnel id: %s", argv[3]);
> + return 0;
> +}
> +if (!strtou16(argv[4], _conf.pr_session_id)) {
> + option_error("pipex-l2tp: invalid local call id: %s", argv[4]);
> + return 0;
> +}
> +if (!strtou16(argv[5], _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 

[RFC] pppd: add pipex(4) L2TP control support

2020-05-25 Thread Sergey Ryazanov
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_addr))
+   return 0;
+if (!(port = strtoul(c + 1, , 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, , 0);
+
+return *ptr == '\0' ? 1 : 0;
+}
+
+static int
+setpipexl2tp(argv)
+char **argv;
+{
+BZERO((char *)_conf, sizeof(pipex_conf));
+
+if (!inet_atoss(argv[0], _conf.pr_local_address)) {
+   option_error("pipex-l2tp: invalid local address of tunnel: %s", 
argv[0]);
+   return 0;
+}
+if (!inet_atoss(argv[1], _conf.pr_peer_address)) {
+   option_error("pipex-l2tp: invalid peer address of tunnel: %s", argv[1]);
+   return 0;
+}
+if (!strtou16(argv[2], _conf.pr_proto.l2tp.tunnel_id)) {
+   option_error("pipex-l2tp: invalid local tunnel id: %s", argv[2]);
+   return 0;
+}
+if (!strtou16(argv[3], _conf.pr_proto.l2tp.peer_tunnel_id)) {
+   option_error("pipex-l2tp: invalid peer tunnel id: %s", argv[3]);
+   return 0;
+}
+if (!strtou16(argv[4], _conf.pr_session_id)) {
+   option_error("pipex-l2tp: invalid local call id: %s", argv[4]);
+   return 0;
+}
+if (!strtou16(argv[5], _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