diff options
author | Daniel Wagner <daniel.wagner@bmw-carit.de> | 2010-10-22 13:55:53 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2010-10-22 23:55:28 +0200 |
commit | 8b49f33573921c27511cb60f7384a48ac3aaa7d4 (patch) | |
tree | 58ac22462ca08c48a55588420047a29711011e2d /plugins/openconnect.c | |
parent | 520d4af146ba1be4b7d76890799342dfe12e5fc7 (diff) | |
download | connman-8b49f33573921c27511cb60f7384a48ac3aaa7d4.tar.gz connman-8b49f33573921c27511cb60f7384a48ac3aaa7d4.tar.bz2 connman-8b49f33573921c27511cb60f7384a48ac3aaa7d4.zip |
Split openconnect into generic vpn and openconnect part
Diffstat (limited to 'plugins/openconnect.c')
-rw-r--r-- | plugins/openconnect.c | 347 |
1 files changed, 33 insertions, 314 deletions
diff --git a/plugins/openconnect.c b/plugins/openconnect.c index 2ddb9046..42192f6a 100644 --- a/plugins/openconnect.c +++ b/plugins/openconnect.c @@ -24,143 +24,23 @@ #endif #include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <stdio.h> #include <errno.h> -#include <sys/ioctl.h> -#include <linux/if_tun.h> -#include <net/if.h> -#include <stdint.h> - -#include <glib/garray.h> -#include <glib/gerror.h> -#include <glib/gmain.h> -#include <glib/gspawn.h> +#include <unistd.h> #define CONNMAN_API_SUBJECT_TO_CHANGE #include <connman/plugin.h> -#include <connman/device.h> -#include <connman/element.h> #include <connman/provider.h> #include <connman/log.h> -#include <connman/element.h> -#include <connman/rtnl.h> #include <connman/task.h> -#include "inet.h" - -enum oc_state { - OC_STATE_UNKNOWN = 0, - OC_STATE_IDLE = 1, - OC_STATE_CONNECT = 2, - OC_STATE_READY = 3, - OC_STATE_DISCONNECT = 4, - OC_STATE_FAILURE = 5, -}; - -struct oc_data { - struct connman_provider *provider; - char *if_name; - unsigned flags; - unsigned int watch; - unsigned int state; - struct connman_task *task; -}; - -static int kill_tun(char *tun_name) -{ - struct ifreq ifr; - int fd, err; - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - sprintf(ifr.ifr_name, "%s", tun_name); +#include "vpn.h" - 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)); - 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)); - close(fd); - return err; - } - - if (ioctl(fd, TUNSETPERSIST, 0)) { - err = -errno; - connman_error("Failed to set tun device %s nonpersistent: %s", - tun_name, strerror(errno)); - close(fd); - return err; - } - close(fd); - DBG("Killed tun device %s", tun_name); - return 0; -} - -static void openconnect_died(struct connman_task *task, void *user_data) -{ - struct connman_provider *provider = user_data; - struct oc_data *data = connman_provider_get_data(provider); - int state = data->state; - - DBG("provider %p data %p", provider, data); - - if (!data) - goto oc_exit; - - kill_tun(data->if_name); - connman_provider_set_data(provider, NULL); - connman_rtnl_remove_watch(data->watch); - - oc_exit: - if (state != OC_STATE_READY && state != OC_STATE_DISCONNECT) - connman_provider_set_state(provider, - CONNMAN_PROVIDER_STATE_FAILURE); - else - connman_provider_set_state(provider, - CONNMAN_PROVIDER_STATE_IDLE); - - connman_provider_set_index(provider, -1); - connman_provider_unref(data->provider); - g_free(data); - - connman_task_destroy(task); -} - -static void vpn_newlink(unsigned flags, unsigned change, void *user_data) -{ - struct connman_provider *provider = user_data; - struct oc_data *data = connman_provider_get_data(provider); - - if ((data->flags & IFF_UP) != (flags & IFF_UP)) { - if (flags & IFF_UP) { - data->state = OC_STATE_READY; - connman_provider_set_state(provider, - CONNMAN_PROVIDER_STATE_READY); - } - } - data->flags = flags; -} - -static void openconnect_task_notify(struct connman_task *task, - DBusMessage *msg, void *user_data) +static int oc_notify(DBusMessage *msg, struct connman_provider *provider) { DBusMessageIter iter, dict; - struct connman_provider *provider = user_data; struct oc_data *data; const char *reason, *key, *value; const char *domain = NULL; - int index; dbus_message_iter_init(msg, &iter); @@ -169,20 +49,17 @@ static void openconnect_task_notify(struct connman_task *task, if (!provider) { connman_error("No provider found"); - return; + return VPN_STATE_FAILURE; } data = connman_provider_get_data(provider); if (!data) { DBG("provider %p no data", provider); - return; + return VPN_STATE_FAILURE; } - if (strcmp(reason, "connect")) { - connman_provider_set_state(provider, - CONNMAN_PROVIDER_STATE_DISCONNECT); - return; - } + if (strcmp(reason, "connect")) + return VPN_STATE_DISCONNECT; domain = connman_provider_get_string(provider, "VPN.Domain"); @@ -220,236 +97,78 @@ static void openconnect_task_notify(struct connman_task *task, dbus_message_iter_next(&dict); } - index = connman_provider_get_index(provider); connman_provider_set_string(provider, "Domain", domain); - data->watch = connman_rtnl_add_newlink_watch(index, - vpn_newlink, provider); - connman_inet_ifup(index); + return VPN_STATE_CONNECT; } -static int oc_connect(struct connman_provider *provider) +static int oc_connect(struct connman_provider *provider, + struct connman_task *task, const char *if_name) { - struct oc_data *data = connman_provider_get_data(provider); - struct ifreq ifr; - int oc_fd, fd, i, index; const char *vpnhost, *vpncookie, *cafile, *mtu; - int ret = 0; - - if (data != NULL) - return -EISCONN; - - data = g_try_new0(struct oc_data, 1); - if (data == NULL) - return -ENOMEM; - - data->provider = connman_provider_ref(provider); - data->watch = 0; - data->flags = 0; - data->task = NULL; - data->state = OC_STATE_IDLE; - - connman_provider_set_data(provider, data); + int fd, err; vpnhost = connman_provider_get_string(provider, "Host"); if (!vpnhost) { connman_error("Host not set; cannot enable VPN"); - ret = -EINVAL; - goto exist_err; + return -EINVAL; } vpncookie = connman_provider_get_string(provider, "OpenConnect.Cookie"); if (!vpncookie) { connman_error("OpenConnect.Cookie not set; cannot enable VPN"); - ret = -EINVAL; - goto exist_err; + return -EINVAL; } cafile = connman_provider_get_string(provider, "OpenConnect.CACert"); mtu = connman_provider_get_string(provider, "VPN.MTU"); - fd = open("/dev/net/tun", O_RDWR); - if (fd < 0) { - i = -errno; - connman_error("Failed to open /dev/net/tun: %s", - strerror(errno)); - ret = i; - goto exist_err; - } - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - - for (i = 0; i < 256; i++) { - sprintf(ifr.ifr_name, "vpn%d", i); - - if (!ioctl(fd, TUNSETIFF, (void *)&ifr)) - break; - } - - if (i == 256) { - connman_error("Failed to find available tun device"); - close(fd); - ret = -ENODEV; - goto exist_err; - } - - data->if_name = (char *)g_strdup(ifr.ifr_name); - if (!data->if_name) { - ret = -ENOMEM; - goto exist_err; - } - - if (ioctl(fd, TUNSETPERSIST, 1)) { - i = -errno; - connman_error("Failed to set tun persistent: %s", - strerror(errno)); - close(fd); - ret = i; - goto exist_err; - } - - close(fd); - - index = connman_inet_ifindex(data->if_name); - if (index < 0) { - connman_error("Failed to get tun ifindex"); - kill_tun(data->if_name); - ret = -EIO; - goto exist_err; - } - connman_provider_set_index(provider, index); - - data->task = connman_task_create(OPENCONNECT); - - if (data->task == NULL) { - ret = -ENOMEM; - kill_tun(data->if_name); - goto exist_err; - } - - if (connman_task_set_notify(data->task, "notify", - openconnect_task_notify, provider)) { - ret = -ENOMEM; - kill_tun(data->if_name); - connman_task_destroy(data->task); - data->task = NULL; - goto exist_err; - } - if (cafile) - connman_task_add_argument(data->task, "--cafile", + connman_task_add_argument(task, "--cafile", (char *)cafile); if (mtu) - connman_task_add_argument(data->task, "--mtu", (char *)mtu); + connman_task_add_argument(task, "--mtu", (char *)mtu); - connman_task_add_argument(data->task, "--syslog", NULL); - connman_task_add_argument(data->task, "--cookie-on-stdin", NULL); + connman_task_add_argument(task, "--syslog", NULL); + connman_task_add_argument(task, "--cookie-on-stdin", NULL); - connman_task_add_argument(data->task, "--script", + connman_task_add_argument(task, "--script", SCRIPTDIR "/openconnect-script"); - connman_task_add_argument(data->task, "--interface", data->if_name); + connman_task_add_argument(task, "--interface", if_name); - connman_task_add_argument(data->task, (char *)vpnhost, NULL); + connman_task_add_argument(task, (char *)vpnhost, NULL); - ret = connman_task_run(data->task, openconnect_died, provider, - &oc_fd, NULL, NULL); - if (ret) { - connman_error("Openconnect failed to start"); - kill_tun(data->if_name); - ret = -EIO; - connman_task_destroy(data->task); - data->task = NULL; - goto exist_err; + err = connman_task_run(task, vpn_died, provider, + &fd, NULL, NULL); + if (err < 0) { + connman_error("openconnect failed to start"); + return -EIO; } - DBG("openconnect started with dev %s", data->if_name); - - if (write(oc_fd, vpncookie, strlen(vpncookie)) != - (ssize_t)strlen(vpncookie) || - write(oc_fd, "\n", 1) != 1) { + if (write(fd, vpncookie, strlen(vpncookie)) != + (ssize_t)strlen(vpncookie) || + write(fd, "\n", 1) != 1) { connman_error("openconnect failed to take cookie on stdin"); - connman_provider_set_data(provider, NULL); - connman_task_stop(data->task); - ret = -EIO; - goto exist_err; + return -EIO; } - data->state = OC_STATE_CONNECT; - - return -EINPROGRESS; - - exist_err: - connman_provider_set_index(provider, -1); - connman_provider_set_data(provider, NULL); - connman_provider_unref(data->provider); - g_free(data); - - return ret; -} - -static int oc_probe(struct connman_provider *provider) -{ return 0; } -static int oc_disconnect(struct connman_provider *provider) -{ - struct oc_data *data = connman_provider_get_data(provider); - - DBG("disconnect provider %p:", provider); - - if (data == NULL) - return 0; - - if (data->watch != 0) - connman_rtnl_remove_watch(data->watch); - - data->watch = 0; - data->state = OC_STATE_DISCONNECT; - connman_task_stop(data->task); - - return 0; -} - -static int oc_remove(struct connman_provider *provider) -{ - struct oc_data *data; - - data = connman_provider_get_data(provider); - connman_provider_set_data(provider, NULL); - if (data == NULL) - return 0; - - if (data->watch != 0) - connman_rtnl_remove_watch(data->watch); - data->watch = 0; - connman_task_stop(data->task); - - g_usleep(G_USEC_PER_SEC); - kill_tun(data->if_name); - return 0; -} - -static struct connman_provider_driver provider_driver = { - .name = "openconnect", - .disconnect = oc_disconnect, +static struct vpn_driver vpn_driver = { + .notify = oc_notify, .connect = oc_connect, - .probe = oc_probe, - .remove = oc_remove, }; static int openconnect_init(void) { - connman_provider_driver_register(&provider_driver); - - return 0; + return vpn_register("openconnect", &vpn_driver, OPENCONNECT); } static void openconnect_exit(void) { - connman_provider_driver_unregister(&provider_driver); + vpn_unregister("openconnect"); } CONNMAN_PLUGIN_DEFINE(openconnect, "OpenConnect VPN plugin", VERSION, |