VPN Connections
A Virtual Private Network (VPN) connects 2 computers securely and privately over the internet. Using the VPN service, you can allow the users of your application to initialize the VPN device, and manage routing, DNS, and firewall features. A VPN connection consists of multiple components, mainly with the VPN server and client connecting over a tunnel.
The main features of the VPN Service API include:
-
VPN manager
You can create or initialize the tunnel interface for the VPN device with various functions. The application can use those functions to get various tunnel details, such as the tunnel ID and tunnel name, MTU for the tunnel interface, and connection statistics.
You can also set various details, such as the MTU for the tunnel interface, and the session name.
The
vpnsvc_tun_s
structure contains detailed information about the tunnel interface, such as the ID, name, and MTU. The possible errors are defined with thevpnsvc_error_e
enumerator.Table: Common macros
Macro Description VPNSVC_IP4_STRING_LEN
IPv4 address string length VPNSVC_VPN_IFACE_NAME_LEN
VPN interface name length VPNSVC_SESSION_STRING_LEN
Session name string length -
VPN profile
You can map the VPN profile and get details about the VPN service by using the vpnsvc_h handle.
The VPN profile provides different functions for routing management, DNS management, and firewall management:
- The
vpnsvc_init()
function is used to a initialize the VPN interface and get the handle. - The
vpnsvc_h
handle is used to configure the tunnel interface before using the VPN application control to ask the user permission to connect to the VPN service. - The
vpnsvc_block_networks()
function is used to block network traffic by creating a route parameter for allowed VPN and original interface routes.
- The
-
VPN statistics
The VPN service allows you to track data transfer information. Use the VPN statistics to gather and reset statistics on network usage, such as the size of the sent or received data, in bytes:
- The
vpnsvc_read()
function is used to read the data from tunnel interface in a specified time period. - The
vpnsvc_write()
function is used to write data to a tunnel file descriptor with a specific size.
- The
The VPN service uses 2 mechanisms for managing access control between the application and service:
-
Privilege:
The application needs the partner level privilege for accessing the VPN service daemon.
-
Application control:
Connecting or disconnecting from a VPN network requires user permission, which is requested by invoking the VPN application control.
VPN Connection Components
A VPN connection includes the following components:
-
VPN server
A computer that accepts VPN connections from VPN clients.
-
VPN client
A computer that initiates a VPN connection to a VPN server. A VPN client can be an individual computer or a router.
-
Tunnel
The portion of the connection in which your data is encapsulated.
-
VPN connection
The portion of the connection in which your data is encrypted. For typical secure VPN connections, the data is encrypted and encapsulated along the same portion of the connection.
-
Tunneling protocols
Protocols that are used to manage tunnels and encapsulate private data. Data that is tunneled must also be encrypted to be a VPN connection.
-
Tunneled data
Data that is usually sent across a private point-to-point link.
-
Transit inter-network
The shared or public network crossed by the encapsulated data. The transit inter-network can be the Internet or a private IP-based intranet.
Prerequisites
To enable your application to use the VPN service functionality:
-
To use the VPN Service API, the application has to request permission by adding the following privilege to the
tizen-manifest.xml
file:<privileges> <privilege>http://developer.samsung.com/tizen/vpnservice</privilege> </privileges>
-
To use the functions and data types of the VPN Service API, include the
<vpn_service.h>
header file in your application:#include <vpn_service.h>
-
To be able to use all VPN functions, you must create a handle that contains information about the VPN. At the beginning, create a vpnsvc_h type variable, which is a
void*
that stores the VPN handle.vpnsvc_h handle = NULL;
-
Create the VPN handle using the
vpnsvc_init()
function that allows you to obtain the VPN state and data transfer information:char *name = TEST_VPN_IF_NAME; int ret = VPNSVC_ERROR_NONE; ret = vpnsvc_init(name, &handle); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_init failed: %d\n", ret);
-
When the VPN handle is no longer needed, destroy it using the
vpnsvc_deinit()
function:if (handle) vpnsvc_deinit(handle); handle = NULL;
Getting Interface Parameters
To get the interface parameters after successfully initializing the VPN service:
-
Get the interface file descriptor using the
vpnsvc_get_iface_fd()
function:int int_value; if (vpnsvc_get_iface_fd(handle, &int_value) == VPNSVC_ERROR_NONE) printf("iface_fd: %d\n", int_value);
-
Get the interface index using the
vpnsvc_get_iface_index()
function:int int_value; if (vpnsvc_get_iface_index(handle, &int_value) == VPNSVC_ERROR_NONE) printf("iface_index: %d\n", int_value);
-
Get the interface name using the
vpnsvc_get_iface_name()
function:char *result_name = NULL; int ret = VPNSVC_ERROR_NONE; ret = vpnsvc_get_iface_name(handle, &result_name); if (ret == VPNSVC_ERROR_NONE) printf("iface_name: %s\n", result_name);
-
Get the session for the interface using the
vpnsvc_get_session()
function:int ret = VPNSVC_ERROR_NONE; char *get_session = NULL; ret = vpnsvc_get_session(handle, &get_session); printf("Session Name = %s\n", get_session); printf("vpnsvc_set_session succeeded!\n");
Setting Interface Parameters
To set the interface parameters:
-
Set the MTU(Maximum Transmission Unit) configuration for the tunnel interface using the
vpnsvc_set_mtu()
function, and update the value using thevpnsvc_update_settings()
function:int ret; ret = vpnsvc_set_mtu(handle, 9000); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_set_mtu failed!\n"); else printf("vpnsvc_set_mtu succeeded!\n"); ret = vpnsvc_update_settings(handle); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_update_settings failed!\n"); else printf("vpnsvc_update_settings succeeded!\n");
-
Set the session name for the tunnel interface using the
vpnsvc_set_session()
function:char *set_session = "vpnsvc_test VPN Session"; int ret; ret = vpnsvc_set_session(handle, set_session); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_set_session failed!\n");
It does not need to use vpnsvc_update_settings()
function to apply the session name.
Configuring the Interface and Connecting to the Service
To configure the interface and connect to the VPN service through an application control:
-
Define a function to launch the VPN application control and a callback to handle the results:
#include <app_control.h> void launch_vpn_service_appcontrol(void) { app_control_h service; app_control_create(&service); app_control_set_operation(service, APP_CONTROL_OPERATION_SETTING_VPN); app_control_add_extra_data(service, APP_CONTROL_DATA_TYPE, "up"); app_control_add_extra_data(service, APP_CONTROL_DATA_NAME, "tizen"); app_control_set_launch_mode(service, APP_CONTROL_LAUNCH_MODE_GROUP); app_control_send_launch_request(service, vpn_appcontrol_result_cb, NULL); app_control_destroy(service); } static void vpn_appcontrol_result_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data) { char *result_txt; switch (result) { case APP_CONTROL_RESULT_APP_STARTED: case APP_CONTROL_RESULT_SUCCEEDED: dlog_print(DLOG_INFO, LOG_TAG, "Success!"); break; case APP_CONTROL_RESULT_FAILED: dlog_print(DLOG_INFO, LOG_TAG, "Failed!"); break; case APP_CONTROL_RESULT_CANCELED: dlog_print(DLOG_INFO, LOG_TAG, "Canceled!"); break; } app_control_get_extra_data(reply, APP_CONTROL_DATA_TEXT, &result_txt); dlog_print(DLOG_INFO, LOG_TAG, "Result: %s", result_txt); }
-
Protect the underlying VPN traffic to be routed to the VPN itself by binding the socket to the underlying network interface, such as
wlan0
:int sock; int ret; ret = vpnsvc_protect(handle, sock, "wlan0"); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_protect failed!\n"); else printf("vpnsvc_protect succeeded!\n");
-
Set up the connection information, which includes the local IP address and the remote IP address:
int ret; char local[VPNSVC_IP4_STRING_LEN] = {'\0',}; char remote[VPNSVC_IP4_STRING_LEN] = {'\0',}; if (!handle) { printf("invalid handle\n"); return -1; } strncpy(local, "192.168.0.82", VPNSVC_IP4_STRING_LEN); strncpy(remote, "192.168.0.1", VPNSVC_IP4_STRING_LEN); /* Local IP address */ ret = vpnsvc_set_local_ip_address(handle, local); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_set_local_ip_address failed!\n"); else printf("vpnsvc_set_local_ip_address succeeded!\n"); /* Remote IP address */ ret = vpnsvc_set_remote_ip_address(handle, remote); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_set_remote_ip_address failed!\n"); else printf("vpnsvc_set_remote_ip_address succeeded!\n");
-
Update the vpnsvc_h handle with the connection information by calling the
vpnsvc_update_settings()
function:ret = vpnsvc_update_settings(handle); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_update_settings failed!\n"); else printf("vpnsvc_update_settings succeeded!\n");
-
Launch the application control to allow the user to connect to the VPN service:
launch_vpn_service_appcontrol();
Blocking and Unblocking Networks
To block or unblock the network:
- Block all traffic, except specified allowed networks, and send the specified UP addresses to a specified interface:
- Specify networks to be allowed over the VPN Interface (e.g., tun0) For example:
size_t num_allow_routes_vpn = 2;
char *routes_dest_vpn_addr[num_allow_routes_vpn];
int routes_vpn_prefix[num_allow_routes_vpn];
// Example: Allow a specific corporate server (e.g., an internal resource)
memset(routes_dest_vpn_addr[0], 0, sizeof(char) * VPNSVC_IP4_STRING_LEN);
strncpy(routes_dest_vpn_addr[0], "10.10.20.30", VPNSVC_IP4_STRING_LEN - 1);
routes_vpn_prefix[0] = 32; // 32 means a single host
printf("VPN Allowed Network 1: %s/%d\n", routes_dest_vpn_addr[0], routes_vpn_prefix[0]);
memset(routes_dest_vpn_addr[1], 0, sizeof(char) * VPNSVC_IP4_STRING_LEN);
strncpy(routes_dest_vpn_addr[1], "203.0.113.10", VPNSVC_IP4_STRING_LEN - 1);
routes_vpn_prefix[1] = 32; // 32 for a single host
printf("VPN Allowed Network 2: %s/%d\n", routes_dest_vpn_addr[1], routes_vpn_prefix[1]);
- Specify networks to be allowed over the original Interface (e.g., wlan0) Traffic to these destinations will bypass the VPN and use the physical interface directly. For example:
size_t num_allow_routes_orig = 2;
char *routes_dest_orig_addr[num_allow_routes_orig];
int routes_orig_prefix[num_allow_routes_orig];
memset(routes_dest_orig_addr[0], 0, sizeof(char) * VPNSVC_IP4_STRING_LEN);
strncpy(routes_dest_orig_addr[0], "192.168.1.100", VPNSVC_IP4_STRING_LEN - 1);
routes_orig_prefix[0] = 32; // /32 for a single host
printf("Original Interface Allowed Network 1: %s/%d\n", routes_dest_orig_addr[0], routes_orig_prefix[0]);
// Example: Allow access to the local router's admin page
memset(routes_dest_orig_addr[1], 0, sizeof(char) * VPNSVC_IP4_STRING_LEN);
strncpy(routes_dest_orig_addr[1], "192.168.1.1", VPNSVC_IP4_STRING_LEN - 1);
routes_orig_prefix[1] = 32; // /32 for a single host
printf("Original Interface Allowed Network 2: %s/%d\n", routes_dest_orig_addr[1], routes_orig_prefix[1]);
- Use the vpnsvc_block_networks() function to allow the specified networks:
ret = vpnsvc_block_networks(handle,
routes_dest_vpn_addr, routes_vpn_prefix, num_allow_routes_vpn,
routes_dest_orig_addr, routes_orig_prefix, num_allow_routes_orig);
if (ret != VPNSVC_ERROR_NONE) {
printf("vpnsvc_block_networks failed! Error code: %d\n", ret);
// It's good practice to map error codes to messages if possible
switch (ret) {
case VPNSVC_ERROR_INVALID_PARAMETER:
printf(" Reason: Invalid parameter (e.g., NULL handle, empty address arrays, num_routes > 255).\n");
break;
case VPNSVC_ERROR_IPC_FAILED:
printf(" Reason: Cannot connect to VPN service daemon.\n");
break;
case VPNSVC_ERROR_PERMISSION_DENIED:
printf(" Reason: Permission denied. Check if the application has the required privileges:\n");
printf(" - http://tizen.org/privilege/vpnservice\n");
printf(" - http://tizen.org/privilege/internet\n");
break;
case VPNSVC_ERROR_NOT_SUPPORTED:
printf(" Reason: This feature is not supported on the device.\n");
break;
default:
printf(" Reason: Unknown error.\n");
break;
}
} else {
printf("vpnsvc_block_networks succeeded!\n");
printf("All network traffic is now blocked EXCEPT for the specified VPN and Original interface routes.\n");
}
if (ret != VPNSVC_ERROR_NONE)
printf("vpnsvc_block_networks failed!\n");
else
printf("vpnsvc_block_networks succeeded!\n");
-
Remove any restrictions from the VPN network:
int ret; if (!handle) { printf("invalid handle\n"); return -1; } ret = vpnsvc_unblock_networks(handle); if (ret != VPNSVC_ERROR_NONE) printf("vpnsvc_unblock_networks failed!\n"); else printf("vpnsvc_unblock_networks succeeded!\n");
Reading and Writing Data
To read or write data:
-
Check whether there is data to read within a specified time period:
int ret; int timeout_ms = 20; // This can block until there is data available for reading from the VPN interface, or the timeout expires. ret = vpnsvc_read(handle, timeout_ms); if (ret == VPNSVC_ERROR_NONE) { read_data(handle); } else if (ret == VPNSVC_ERROR_TIMEOUT) { // Handle timeout } else { // Handle errors }
-
Read data from the VPN interface: If
VPNSVC_ERROR_NONE
returns, you can proceed to read data from the VPN interface. You can obtain the file descriptor usingvpnsvc_get_iface_fd()
and then read the data from it.
bool get_iftace_fd(vpnsvc_h handle, int* iface_fd) {
if (vpnsvc_get_iface_fd(handle, iface_fd) != VPNSVC_ERROR_NONE) {
printf("Failed to get VPN interface file descriptor.\n");
return false;
}
if (*iface_fd <= 0) {
printf("Invalid file descriptor.\n");
return false;
}
return true;
}
void read_data(vpnsvc_h handle) {
int iface_fd = 0;
if (!get_iftace_fd(handle, &iface_fd)) {
return;
}
char buffer[1024];
ssize_t bytes_read = read(iface_fd, buffer, sizeof(buffer));
if (bytes_read > 0)
// process the read data
-
Write data directly to the underlying socket using a system call for performance. The number of bytes written is returned on success (the same as the system write call).
int ret; char *message = "test message"; ret = vpnsvc_write(handle, message, strlen(message)); if (ret < 0) printf("vpnsvc_write: failed!\n"); else if (ret == 0) printf("vpnsvc_write: Nothing written!\n"); else printf("vpnsvc_read: %d bytes written!\n", ret);
Related information
- Dependencies
- Since Tizen 3.0
- API References