0

I did not found any examples how to implement L2TPv3 over IP

I found only a couple of open source implementations of L2TP which are:

L2TPv3 rfc says nothing how it is implemented in Linux which is obvious

kernel documentation: https://github.com/torvalds/linux/blob/master/Documentation/networking/l2tp.txt says we must use netlink + standard sockets which tells us something. But I do not understand why we must use netlink along with standard sockets?

kernel header file: https://github.com/torvalds/linux/blob/master/include/uapi/linux/l2tp.h it has tons of enums and commands for netlink + l2tpip structure for . I am confused of how to use them properly.

And final part of L2TPv3 control exchange establishment (SCCRQ, SCCRP, SCCCN). Having read kernel documentation I have only own understanding which might not be right but here it is.

server side:

  1. Prepare tunnel 0 socket

  2. Create genl socket for l2tp

  3. Create standard socket filling l2tpip structure (socket create + bind) where tunnel_id is 0

  4. Using genl socket create tunnel 0

  5. Wait for SCCRQ (As I understand header will have control connection id equals zero)

  6. On received SCCRQ on tunnel 0 socket

  7. From received SCCRQ grab AVL's Assigned Control Connection ID which is received_tunnel_id on other side

  8. Generate local_tunnel_id for our side

  9. Create standard socket filling l2tpip structure (socket create + bind) where tunnel_id is local_tunnel_id

  10. Using genl socket create tunnel with local_tunnel_id

  11. Send SCCRP which has header's Control Connection ID equal to received_tunnel_id and AVL Assigned Control Connection ID equal to local_tunnel_id

  12. Wait for SCCN on that socket

client side

  1. I do not know how it is done on that side

As I understand further communication will be over second standard socket and tunnel id zero is receiving ONLY SCCRQ

It would be great to get clarification on these details

Jason Aller
  • 3,541
  • 28
  • 38
  • 38

1 Answers1

0

Apologies that this reply is so late! But hopefully it can still be useful for you or others.

I'll try to address the different aspects of your question in turn.

But I do not understand why we must use netlink along with standard sockets?

The Linux L2TP subsystem deals with the data plane only (i.e. user data packets being carried over L2TP sessions). User space is tasked with handling the control plane (L2TP control protocol exchanges).

So broadly speaking, user space creates a tunnel socket in order to exchange L2TP control messages with the peer. Once a tunnel is established (SCCRQ/SCCRP/SCCCN), the tunnel FD is passed to the kernel using the netlink API when creating the kernel tunnel context. That same tunnel FD is then used for session data packets in the tunnel.

kernel header file: https://github.com/torvalds/linux/blob/master/include/uapi/linux/l2tp.h it has tons of enums and commands for netlink + l2tpip structure for . I am confused of how to use them properly.

This blog post might help you: Linux and L2TP -- a peek under the hood. It covers the commands in the netlink API and sketches out how to use them.

And final part of L2TPv3 control exchange establishment (SCCRQ, SCCRP, SCCCN). Having read kernel documentation I have only own understanding which might not be right but here it is.

On the server side you're broadly correct, with the following caveats:

  • Step 4 is unnecessary. You don't need to create a kernel context for tunnel ID 0 since you're only expecting control packets (specifically, SCCRQ, and in some corner cases STOPCCN) to tunnel ID 0.
  • Step 9 should also connect(2) to the peer's address and tunnel ID.
  • Step 10 could be considered to be done too early, since the control protocol can of course fail before the tunnel is established. From the server's perspective, the tunnel can be considered to be established once the SCCCN message has been ACKed by the transport. This said there's no harm creating the kernel tunnel context early so long as you make sure you tear it down in case the control protocol fails.

client side... I do not know how it is done on that side

It's the same basic process as for the server side.

User space should carry out the control protocol message exchange (SCCRQ/SCCRP/SCCCN), and once that has successfully completed use netlink messages to instantiate an L2TP tunnel context in the kernel.

  1. Create a genl socket for L2TP.
  2. Generate a local tunnel ID.
  3. Create a tunnel socket which should be bound to the local address and local tunnel ID. Don't connect the socket yet.
  4. Prepare the SCCRQ message. This should be sent to the peer using tunnel ID 0 in the L2TP header. You'll need to use sendto(2) semantics in order to do this.
  5. Wait for SCCRP from the peer. On receipt of SCCRP you'll need to connect the socket to the tunnel ID called out in the Assigned Control Connection AVP in the SCCRP message.
  6. Send SCCCN.
  7. Wait for SCCCN to be ACKed. On receipt of the SCCCN ACK use the L2TP genl socket to create a kernel tunnel context using the tunnel IDs from the control protocol exchange.

As I understand further communication will be over second standard socket and tunnel id zero is receiving ONLY SCCRQ

Yes. One way to think of the tunnel ID zero socket is as being akin to a socket you'd listen(2) on for an HTTP server. The purpose of the socket is to receive requests to a well-known port, and subsequent message exchanges occur over a connection-specific socket on a different port.

Of course IP doesn't have ports, but the zero tunnel ID is playing the same role for an L2TPv3 IP-encap server.

Tom Parkin
  • 169
  • 3