Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1842)

Unified Diff: plugins/vpn.c

Issue 6513009: flimflam: Add L2TP/IPsec VPN plugin (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/flimflam.git@master
Patch Set: Add gateway when requested Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « plugins/vpn.h ('k') | scripts/libppp-plugin.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: plugins/vpn.c
diff --git a/plugins/vpn.c b/plugins/vpn.c
index af0e082c7276f9424023b3ad2274df21e5867fe2..131a0f118f321b7dc7b528a534e7b2c100674b88 100644
--- a/plugins/vpn.c
+++ b/plugins/vpn.c
@@ -25,7 +25,6 @@
* vpn plugin is responsible for launching the external process and
* handling notification callbacks to clock the provider state machine.
*
- * TODO(sleffler) currently assumes extern vpn service uses tun but not all do
* TODO(sleffler) seems to make more sense in src than plugins
*/
@@ -57,7 +56,7 @@
#include "vpn.h"
-#define _DBG_VPN(fmt, arg...) DBG(DBG_VPN, fmt, ## arg)
+#define _DBG_VPN(fmt, arg...) DBG(DBG_VPN, fmt, ## arg)
struct vpn_data {
struct connman_provider *provider;
@@ -77,27 +76,40 @@ struct vpn_driver_data {
static GHashTable *driver_hash = NULL;
-static int kill_tun(char *tun_name)
+static int kill_tun(struct connman_provider *provider)
{
+ struct vpn_data *data = connman_provider_get_data(provider);
+ struct vpn_driver_data *vpn_driver_data;
+ const char *name;
struct ifreq ifr;
int fd, err;
+ if (data == NULL)
+ return -1;
+
+ name = connman_provider_get_driver_name(provider);
+ vpn_driver_data = g_hash_table_lookup(driver_hash, name);
+
+ if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver !=NULL &&
+ vpn_driver_data->vpn_driver->flags == VPN_FLAG_NO_TUN)
+ return 0;
+
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
- strncpy(ifr.ifr_name, tun_name, sizeof(ifr.ifr_name));
+ strncpy(ifr.ifr_name, data->if_name, sizeof(ifr.ifr_name));
fd = open("/dev/net/tun", O_RDWR);
if (fd < 0) {
err = -errno;
connman_error("Failed to open /dev/net/tun to device %s: %s",
- tun_name, strerror(errno));
+ data->if_name, strerror(errno));
return err;
}
if (ioctl(fd, TUNSETIFF, (void *)&ifr)) {
err = -errno;
connman_error("Failed to TUNSETIFF for device %s to it: %s",
- tun_name, strerror(errno));
+ data->if_name, strerror(errno));
close(fd);
return err;
}
@@ -105,12 +117,12 @@ static int kill_tun(char *tun_name)
if (ioctl(fd, TUNSETPERSIST, 0)) {
err = -errno;
connman_error("Failed to set tun device %s nonpersistent: %s",
- tun_name, strerror(errno));
+ data->if_name, strerror(errno));
close(fd);
return err;
}
close(fd);
- _DBG_VPN("Killed tun device %s", tun_name);
+ _DBG_VPN("Killed tun device %s", data->if_name);
return 0;
}
@@ -125,7 +137,7 @@ void vpn_died(struct connman_task *task, void *user_data)
if (!data)
goto vpn_exit;
- kill_tun(data->if_name);
+ kill_tun(provider);
connman_provider_set_data(provider, NULL);
connman_rtnl_remove_watch(data->watch);
@@ -144,7 +156,38 @@ vpn_exit:
connman_task_destroy(task);
}
-static void vpn_newlink(const char *ifname, unsigned flags, unsigned change, void *user_data)
+int vpn_set_ifname(struct connman_provider *provider, const char *ifname)
+{
+ struct vpn_data *data = connman_provider_get_data(provider);
+ int index;
+
+ if (data == NULL) {
+ _DBG_VPN("%s: provider data not accessible", __func__);
+ return -EIO;
+ }
+
+ if (ifname == NULL) {
+ _DBG_VPN("%s: ifname not provided", __func__);
+ return -EIO;
+ }
+
+ index = connman_inet_ifindex(ifname);
+ if (index < 0) {
+ _DBG_VPN("%s: could not get ifindex from %s", __func__, ifname);
+ return -EIO;
+ }
+
+ data->if_name = (char *)g_strdup(ifname);
+ connman_provider_set_index(provider, index);
+
+ /* Set connect state to retry creating ipconfig with index above. */
+ connman_provider_set_state(provider, CONNMAN_PROVIDER_STATE_CONNECT);
+
+ return 0;
+}
+
+static void vpn_newlink(const char *ifname, unsigned flags, unsigned change,
+ void *user_data)
{
struct connman_provider *provider = user_data;
struct vpn_data *data = connman_provider_get_data(provider);
@@ -159,7 +202,7 @@ static void vpn_newlink(const char *ifname, unsigned flags, unsigned change,
data->flags = flags;
}
-static void vpn_notify(struct connman_task *task,
+static DBusMessage *vpn_notify(struct connman_task *task,
DBusMessage *msg, void *user_data)
{
struct connman_provider *provider = user_data;
@@ -173,7 +216,7 @@ static void vpn_notify(struct connman_task *task,
name = connman_provider_get_driver_name(provider);
vpn_driver_data = g_hash_table_lookup(driver_hash, name);
if (vpn_driver_data == NULL)
- return;
+ return NULL;
state = vpn_driver_data->vpn_driver->notify(msg, provider);
switch (state) {
@@ -193,34 +236,21 @@ static void vpn_notify(struct connman_task *task,
CONNMAN_PROVIDER_STATE_DISCONNECT);
break;
}
+
+ return NULL;
}
-static int vpn_connect(struct connman_provider *provider)
+static int vpn_create_tun(struct connman_provider *provider)
{
struct vpn_data *data = connman_provider_get_data(provider);
- struct vpn_driver_data *vpn_driver_data;
struct ifreq ifr;
- const char *name;
int i, fd, index;
int ret = 0;
- if (data != NULL)
- return -EISCONN;
-
- data = g_try_new0(struct vpn_data, 1);
- if (data == NULL)
- return -ENOMEM;
-
- data->provider = connman_provider_ref(provider);
- data->watch = 0;
- data->flags = 0;
- data->task = NULL;
- data->state = VPN_STATE_IDLE;
-
- connman_provider_set_data(provider, data);
-
- name = connman_provider_get_driver_name(provider);
- vpn_driver_data = g_hash_table_lookup(driver_hash, name);
+ if (data == NULL) {
+ connman_error("%s: called out of order", __func__);
+ return -EIO;
+ }
fd = open("/dev/net/tun", O_RDWR);
if (fd < 0) {
@@ -269,24 +299,65 @@ static int vpn_connect(struct connman_provider *provider)
index = connman_inet_ifindex(data->if_name);
if (index < 0) {
connman_error("%s: failed to get tun ifindex", __func__);
- kill_tun(data->if_name);
+ kill_tun(provider);
ret = -EIO;
goto exist_err;
}
connman_provider_set_index(provider, index);
+ return 0;
+
+exist_err:
+ return ret;
+}
+
+static int vpn_connect(struct connman_provider *provider)
+{
+ struct vpn_data *data = connman_provider_get_data(provider);
+ struct vpn_driver_data *vpn_driver_data;
+ const char *name;
+ int ret = 0;
+
+ if (data != NULL) {
+ _DBG_VPN("%s: data != NULL", __func__);
+ return -EISCONN;
+ }
+
+ data = g_try_new0(struct vpn_data, 1);
+ if (data == NULL)
+ return -ENOMEM;
+
+ data->provider = connman_provider_ref(provider);
+ data->watch = 0;
+ data->flags = 0;
+ data->task = NULL;
+ data->state = VPN_STATE_IDLE;
+
+ connman_provider_set_data(provider, data);
+
+ name = connman_provider_get_driver_name(provider);
+ vpn_driver_data = g_hash_table_lookup(driver_hash, name);
+
+ if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver != NULL &&
+ vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
+
+ ret = vpn_create_tun(provider);
+ if (ret < 0)
+ goto exist_err;
+ }
+
data->task = connman_task_create(vpn_driver_data->program);
if (data->task == NULL) {
ret = -ENOMEM;
- kill_tun(data->if_name);
+ kill_tun(provider);
goto exist_err;
}
if (connman_task_set_notify(data->task, "notify",
vpn_notify, provider)) {
ret = -ENOMEM;
- kill_tun(data->if_name);
+ kill_tun(provider);
connman_task_destroy(data->task);
data->task = NULL;
goto exist_err;
@@ -295,7 +366,7 @@ static int vpn_connect(struct connman_provider *provider)
ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
data->if_name);
if (ret < 0) {
- kill_tun(data->if_name);
+ kill_tun(provider);
connman_task_destroy(data->task);
data->task = NULL;
goto exist_err;
@@ -355,7 +426,6 @@ static int vpn_remove(struct connman_provider *provider)
struct vpn_data *data;
data = connman_provider_get_data(provider);
- connman_provider_set_data(provider, NULL);
if (data == NULL)
return 0;
@@ -365,7 +435,8 @@ static int vpn_remove(struct connman_provider *provider)
connman_task_stop(data->task);
g_usleep(G_USEC_PER_SEC);
- kill_tun(data->if_name);
+ kill_tun(provider);
+ connman_provider_set_data(provider, NULL);
return 0;
}
« no previous file with comments | « plugins/vpn.h ('k') | scripts/libppp-plugin.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698