PacketTunnelProvider - Packetflow

I'm implementing a VPN client using PacketTunnelProvider.

I have a C code that talk to my sever, and this C code also has callbacks to my Swift code.

In those callbacks I just need to send / receive packets.

I do not need to create a tunnel with the server, because the C code does it for me.

So my question is, how to get all the packets ? I tried doing it with packetFlow, but without any success.

(And as for the moment, i'm trying to do it at the startTunnelWithOptions function, but not sure if it's the right place)


Thanks!

It sounds like you are directly creating your PacketTunnelProvider instance from within your own code. I do not believe this will work.


My understanding is that the system is responsible for loading your extension, whose principle class is derived from NEPacketTunnelProvider, and then the system creates an instance of your PacketTunnelProvider. The system will load and start your extension in response to either the user starting the tunnel (e.g., in System Preferences Network pane on OS X) or your host app using the NETunnelProviderManager class.

Thanks for the answer, but I'm not doing it from my own code.
The only thing I did from my own code is to configure the VPN (and start it).

Now I have the extension class ( PacketTunnelProvider: NEPacketTunnelProvider ) and there I have the function startTunnelWithOptions(options...)

Here is the problem - In that function Im suppose to create a tunnel, but I dont want a direct tunnel to the server.

I just need to read/write the packets from the OS to my C callback functions.

I assume that when you say you configure and start the VPN from your own code, you are calling

startTunnelWithOptions:andReturnError:
on a NETunnelProviderSession instance obtatined from your configured and saved NETunnelProviderManager.


I do not understand what you mean when you say you do not want a direct tunnel to the server. Perhaps you could elaborate?


I would imagine that in your

startTunnelWithOptions:completionHandler:
method, you would call the imported C functions that create, configure, and start your packet tunnel or VPN session.


From my understanding, your C code cannot directly do things like set network settings (IP address, routes, etc.). The C code would need to somehow pass the network config to the

setTunnelNetworkSettings:completionHandler:
method of your NEPacketTunnelProvider instance.

You are right in your assumption that I call startTunnelWithOptions:andReturnError.

From there all my code is in the extenstion.

Now, I have a C function that I need to call for every packet coming from the OS.

Something like:


packetFlow.readPacketsWithCompletionHandler { inPackets, inProtocols in
            //send packets to my C function
}


The C code is part of the extension. I just dont know how to read packets and transfer them.

Up to now, I tried without success 😟


(And thanks for your time!)

You don't know how to read packets from where? The virtual tunnel device (i.e. packetFlow) or the C code implementing the tunnel/VPN?


Is the problem that

packetFlow.readPacketsWithCompletionHandler
never calls your completion handler with packets?

Yep, that exactly the problem
Edit: and I have this code

let networkSettings = NEPacketTunnelNetworkSettings()
            networkSettings.IPv4Settings = NEIPv4Settings()
           
            let defaultRoute = NEIPv4Route.defaultRoute()
            networkSettings.IPv4Settings?.includedRoutes = [defaultRoute]
           
            networkSettings.IPv6Settings = NEIPv6Settings()
            let defaultRouteIPv6 = NEIPv6Route.defaultRoute()
            networkSettings.IPv6Settings?.includedRoutes = [defaultRouteIPv6]
           
            self.setTunnelNetworkSettings(networkSettings) { (error) -> Void in
                self.pendingStartCompletionHandler?(nil)
                self.pendingStartCompletionHandler = nil
                self.startHandlingPackets()
            }


but Im not getting any packets

Check out the PacketTunnelProvider class in the SimpleTunnel sample code. It uses the

packetFlow
property (inherited from the NEPacketTunnelProvider superclass) to get packets coming from higher levels in the OS and return packets back up to those higher levels. This is where you need to connect your C code. The sample code does this work using a helper class, ClientTunnelConnection, but there’s just a convenience.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I am also facing same issue,Are you able to resolve this issue?

You must give your TUN device an IP address and mask. To do that, change your code:

let networkSettings = NEPacketTunnelNetworkSettings(addresses: ["***.***.***.***"], subnetMasks: ["yyy.yyy.yyy.yyy"] )

where ... the IP address you want to give to your interface, and yyy.yyy.yyy.yyy subnet mask

PacketTunnelProvider - Packetflow
 
 
Q