Hi Daniel,

On Tue, Oct 19, 2010 at 10:08:13AM -0400, Daniel Wagner wrote:
> From: Daniel Wagner <[email protected]>
That's great, thanks for adding this new feature.

I have some generic comments:

1) It seems the openvpn and openconnect plugins share a lot of code. Here is
what I propose:
- Factor this shared code out and dump it in plugins/vpn.c
- Define the vpn_register() and vpn_unregister() routines that would take a
name, a connect() function and register/unregister the corresponding provider.
This would be the only exported vpn API.
- If OPENCONNECT or OPENVPN are defined, then plugins/vpn.c is compiled.

2) I think the connect-openvpn script could be integrated into the existing
connect-vpn one.

Cheers,
Samuel.

> ---
> 
> v1: added missing connect-openvpn test script
> v0: initial version
> 
>  Makefile.plugins         |   21 ++
>  configure.ac             |   17 ++
>  plugins/openvpn.c        |  477 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  scripts/openvpn-script.c |  123 ++++++++++++
>  src/provider.c           |   34 ++--
>  test/connect-openvpn     |   24 +++
>  6 files changed, 681 insertions(+), 15 deletions(-)
>  create mode 100644 plugins/openvpn.c
>  create mode 100644 scripts/openvpn-script.c
>  create mode 100755 test/connect-openvpn
> 
> diff --git a/Makefile.plugins b/Makefile.plugins
> index e6b79b0..8e82c9e 100644
> --- a/Makefile.plugins
> +++ b/Makefile.plugins
> @@ -121,6 +121,21 @@ plugins_openconnect_la_LDFLAGS = $(plugin_ldflags)
>  endif
>  endif
>  
> +if OPENVPN
> +if OPENVPN_BUILTIN
> +builtin_modules += openvpn
> +builtin_sources += plugins/openvpn.c
> +builtin_cflags += -DOPENVPN=\"@open...@\"
> +else
> +plugin_LTLIBRARIES += plugins/openvpn.la
> +plugin_objects += $(plugins_openvpn_la_OBJECTS)
> +plugins_openvpn_la_CFLAGS = $(plugin_cflags) -DOPENVPN=\"@open...@\" \
> +                                     -DSTATEDIR=\""$(statedir)"\" \
> +                                     -DSCRIPTDIR=\""$(build_scriptdir)"\"
> +plugins_openvpn_la_LDFLAGS = $(plugin_ldflags)
> +endif
> +endif
> +
>  if PORTAL
>  if PORTAL_BUILTIN
>  builtin_modules += portal
> @@ -229,6 +244,12 @@ script_PROGRAMS += scripts/openconnect-script
>  scripts_openconnect_script_LDADD = @DBUS_LIBS@
>  endif
>  
> +if OPENVPN
> +script_PROGRAMS += scripts/openvpn-script
> +
> +scripts_openvpn_script_LDADD = @DBUS_LIBS@
> +endif
> +
>  if DHCLIENT
>  script_DATA += scripts/dhclient.conf
>  script_PROGRAMS += scripts/dhclient-script
> diff --git a/configure.ac b/configure.ac
> index 1b52a93..31b91d9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -129,6 +129,23 @@ fi
>  AM_CONDITIONAL(OPENCONNECT, test "${enable_openconnect}" != "no")
>  AM_CONDITIONAL(OPENCONNECT_BUILTIN, test "${enable_openconnect}" = "builtin")
>  
> +AC_ARG_WITH(openvpn, AC_HELP_STRING([--with-openvpn=PROGRAM],
> +        [specify location of openvpn binary]), [path_openvpn=${withval}])
> +
> +AC_ARG_ENABLE(openvpn,
> +     AC_HELP_STRING([--enable-openvpn], [enable openvpn support]),
> +                     [enable_openvpn=${enableval}], [enable_openvpn="no"])
> +if (test "${enable_openvpn}" != "no"); then
> +     if (test -z "${path_openvpn}"); then
> +             AC_PATH_PROG(OPENVPN, [openvpn], [], $PATH:/sbin:/usr/sbin)
> +     else
> +             OPENVPN="${path_openvpn}"
> +             AC_SUBST(OPENVPN)
> +     fi
> +fi
> +AM_CONDITIONAL(OPENVPN, test "${enable_openvpn}" != "no")
> +AM_CONDITIONAL(OPENVPN_BUILTIN, test "${enable_openvpn}" = "builtin")
> +
>  AC_ARG_ENABLE(portal,
>       AC_HELP_STRING([--enable-portal], [enable portal detection support]),
>                       [enable_portal=${enableval}], [enable_portal="no"])
> diff --git a/plugins/openvpn.c b/plugins/openvpn.c
> new file mode 100644
> index 0000000..edb160c
> --- /dev/null
> +++ b/plugins/openvpn.c
> @@ -0,0 +1,477 @@
> +/*
> + *
> + *  Connection Manager
> + *
> + *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
> + *  Copyright (C) 2010  BMW Car IT GmbH. All rights reserved.
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  
> USA
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#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>
> +
> +#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 <connman/dbus.h>
> +
> +#include "inet.h"
> +
> +enum ov_state {
> +     OV_STATE_UNKNOWN       = 0,
> +     OV_STATE_IDLE          = 1,
> +     OV_STATE_CONNECT       = 2,
> +     OV_STATE_READY         = 3,
> +     OV_STATE_DISCONNECT    = 4,
> +     OV_STATE_FAILURE       = 5,
> +};
> +
> +struct ov_data {
> +     struct connman_provider *provider;
> +     char *if_name;
> +     unsigned flags;
> +     unsigned int watch;
> +     unsigned int state;
> +     struct connman_task *task;
> +};
> +
> +static DBusConnection *connection;
> +
> +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);
> +
> +     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 openvpn_died(struct connman_task *task, void *user_data)
> +{
> +     struct connman_provider *provider = user_data;
> +     struct ov_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 != OV_STATE_READY && state != OV_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 ov_data *data = connman_provider_get_data(provider);
> +
> +     if ((data->flags & IFF_UP) != (flags & IFF_UP)) {
> +             if (flags & IFF_UP) {
> +                     data->state = OV_STATE_READY;
> +                     connman_provider_set_state(provider,
> +                                     CONNMAN_PROVIDER_STATE_READY);
> +             }
> +     }
> +     data->flags = flags;
> +}
> +
> +static void openvpn_task_notify(struct connman_task *task,
> +                                 DBusMessage *msg, void *user_data)
> +{
> +     DBusMessageIter iter, dict;
> +     struct connman_provider *provider = user_data;
> +     struct ov_data *data;
> +     const char *reason, *key, *value;
> +     const char *domain = NULL;
> +     int index;
> +
> +     dbus_message_iter_init(msg, &iter);
> +
> +     dbus_message_iter_get_basic(&iter, &reason);
> +     dbus_message_iter_next(&iter);
> +
> +     if (!provider) {
> +             connman_error("No provider found");
> +             return;
> +     }
> +
> +     data = connman_provider_get_data(provider);
> +     if (!data) {
> +             DBG("provider %p no data", provider);
> +             return;
> +     }
> +
> +     if (strcmp(reason, "up")) {
> +             connman_provider_set_state(provider,
> +                                     CONNMAN_PROVIDER_STATE_DISCONNECT);
> +             return;
> +     }
> +
> +     domain = connman_provider_get_string(provider, "VPN.Domain");
> +
> +     dbus_message_iter_recurse(&iter, &dict);
> +
> +     while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
> +             DBusMessageIter entry;
> +
> +             dbus_message_iter_recurse(&dict, &entry);
> +             dbus_message_iter_get_basic(&entry, &key);
> +             dbus_message_iter_next(&entry);
> +             dbus_message_iter_get_basic(&entry, &value);
> +
> +             DBG("%s = %s", key, value);
> +
> +             if (!strcmp(key, "route_gateway_1"))
> +                     connman_provider_set_string(provider, "Gateway", value);
> +
> +             if (!strcmp(key, "route_netmask_1"))
> +                     connman_provider_set_string(provider, "Netmask", value);
> +
> +             if (!strcmp(key, "route_network_1"))
> +                     connman_provider_set_string(provider, "Address", value);
> +
> +             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);
> +}
> +
> +static int ov_connect(struct connman_provider *provider)
> +{
> +     struct ov_data *data = connman_provider_get_data(provider);
> +     struct ifreq ifr;
> +     int fd, i, index;
> +     const char *vpnhost, *cafile, *mtu, *certfile, *keyfile;
> +     int ret = 0;
> +
> +     if (data != NULL)
> +             return -EISCONN;
> +
> +     data = g_try_new0(struct ov_data, 1);
> +     if (data == NULL)
> +             return -ENOMEM;
> +
> +     data->provider = connman_provider_ref(provider);
> +     data->watch = 0;
> +     data->flags = 0;
> +     data->task = NULL;
> +     data->state = OV_STATE_IDLE;
> +
> +     connman_provider_set_data(provider, data);
> +
> +     vpnhost = connman_provider_get_string(provider, "Host");
> +     if (!vpnhost) {
> +             connman_error("Host not set; cannot enable VPN");
> +             ret = -EINVAL;
> +             goto exist_err;
> +     }
> +
> +     cafile = connman_provider_get_string(provider, "OpenVPN.CACert");
> +     certfile = connman_provider_get_string(provider, "OpenVPN.Cert");
> +     keyfile = connman_provider_get_string(provider, "OpenVPN.Key");
> +     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, "tun%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(OPENVPN);
> +
> +     if (data->task == NULL) {
> +             ret = -ENOMEM;
> +             kill_tun(data->if_name);
> +             goto exist_err;
> +     }
> +
> +     if (connman_task_set_notify(data->task, "notify",
> +                                     openvpn_task_notify, provider)) {
> +             ret = -ENOMEM;
> +             kill_tun(data->if_name);
> +             connman_task_destroy(data->task);
> +             data->task = NULL;
> +             goto exist_err;
> +     }
> +
> +     if (mtu)
> +             connman_task_add_argument(data->task, "--mtu", (char *)mtu);
> +
> +     connman_task_add_argument(data->task, "--syslog", NULL);
> +
> +     connman_task_add_argument(data->task, "--script-security", "2");
> +
> +     connman_task_add_argument(data->task, "--up",
> +                                     SCRIPTDIR "/openvpn-script");
> +
> +     connman_task_add_argument(data->task, "--setenv", NULL);
> +     connman_task_add_argument(data->task, "CONNMAN_BUSNAME",
> +                                     dbus_bus_get_unique_name(connection));
> +
> +     connman_task_add_argument(data->task, "--setenv", NULL);
> +     connman_task_add_argument(data->task, "CONNMAN_INTERFACE",
> +                                     CONNMAN_TASK_INTERFACE);
> +
> +     connman_task_add_argument(data->task, "--setenv", NULL);
> +     connman_task_add_argument(data->task, "CONNMAN_PATH",
> +                                     connman_task_get_path(data->task));
> +
> +     connman_task_add_argument(data->task, "--dev", data->if_name);
> +
> +     connman_task_add_argument(data->task, "--tls-client", NULL);
> +     connman_task_add_argument(data->task, "--remote", (char *)vpnhost);
> +     connman_task_add_argument(data->task, "--nobind", NULL);
> +     connman_task_add_argument(data->task, "--persist-key", NULL);
> +     connman_task_add_argument(data->task, "--persist-tun", NULL);
> +
> +     connman_task_add_argument(data->task, "--route-noexec", NULL);
> +     connman_task_add_argument(data->task, "--ifconfig-noexec", NULL);
> +     connman_task_add_argument(data->task, "--up-restart", NULL);
> +
> +     connman_task_add_argument(data->task, "--client", NULL);
> +
> +     if (cafile) {
> +             connman_task_add_argument(data->task, "--ca",
> +                                             (char *)cafile);
> +     }
> +
> +     if (certfile) {
> +             connman_task_add_argument(data->task, "--cert",
> +                                             (char *)certfile);
> +     }
> +
> +     if (keyfile) {
> +             connman_task_add_argument(data->task, "--key",
> +                                             (char *)keyfile);
> +     }
> +
> +
> +     fd = fileno(stderr);
> +     ret = connman_task_run(data->task, openvpn_died, provider,
> +                             NULL, &fd, &fd);
> +     if (ret) {
> +             connman_error("OpenVPN failed to start");
> +             kill_tun(data->if_name);
> +             ret = -EIO;
> +             connman_task_destroy(data->task);
> +             data->task = NULL;
> +             goto exist_err;
> +     }
> +
> +     DBG("openvpn started with dev %s", data->if_name);
> +
> +     data->state = OV_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 ov_probe(struct connman_provider *provider)
> +{
> +     return 0;
> +}
> +
> +static int ov_disconnect(struct connman_provider *provider)
> +{
> +     struct ov_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 = OV_STATE_DISCONNECT;
> +     connman_task_stop(data->task);
> +
> +     return 0;
> +}
> +
> +static int ov_remove(struct connman_provider *provider)
> +{
> +     struct ov_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           = "openvpn",
> +     .disconnect     = ov_disconnect,
> +     .connect        = ov_connect,
> +     .probe          = ov_probe,
> +     .remove = ov_remove,
> +};
> +
> +static int openvpn_init(void)
> +{
> +     connection = connman_dbus_get_connection();
> +
> +     connman_provider_driver_register(&provider_driver);
> +
> +     return 0;
> +}
> +
> +static void openvpn_exit(void)
> +{
> +     connman_provider_driver_unregister(&provider_driver);
> +
> +     dbus_connection_unref(connection);
> +}
> +
> +CONNMAN_PLUGIN_DEFINE(openvpn, "OpenVPN plugin", VERSION,
> +     CONNMAN_PLUGIN_PRIORITY_DEFAULT, openvpn_init, openvpn_exit)
> diff --git a/scripts/openvpn-script.c b/scripts/openvpn-script.c
> new file mode 100644
> index 0000000..8d2c3ff
> --- /dev/null
> +++ b/scripts/openvpn-script.c
> @@ -0,0 +1,123 @@
> +/*
> + *
> + *  Connection Manager
> + *
> + *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
> + *  Copyright (C) 2010  BMW Car IT GmbH. All rights reserved.
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  
> USA
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <dbus/dbus.h>
> +
> +extern char **environ;
> +
> +static void append(DBusMessageIter *dict, const char *pattern)
> +{
> +     DBusMessageIter entry;
> +     const char *key, *value;
> +     char *delim;
> +
> +     delim = strchr(pattern, '=');
> +     *delim = '\0';
> +
> +     key = pattern;
> +     value = delim + 1;
> +
> +     dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
> +                                                     NULL, &entry);
> +
> +     dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
> +
> +     dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
> +
> +     dbus_message_iter_close_container(dict, &entry);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +     DBusConnection *conn;
> +     DBusError error;
> +     DBusMessage *msg;
> +     DBusMessageIter iter, dict;
> +     char **envp, *busname, *interface, *path, *reason;
> +
> +     busname = getenv("CONNMAN_BUSNAME");
> +     interface = getenv("CONNMAN_INTERFACE");
> +     path = getenv("CONNMAN_PATH");
> +
> +     reason = getenv("script_type");
> +
> +     if (!busname || !interface || !path || !reason) {
> +             fprintf(stderr, "Required environment variables not set\n");
> +             return 1;
> +     }
> +     dbus_error_init(&error);
> +
> +     conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
> +     if (conn == NULL) {
> +             if (dbus_error_is_set(&error) == TRUE) {
> +                     fprintf(stderr, "%s\n", error.message);
> +                     dbus_error_free(&error);
> +             } else
> +                     fprintf(stderr, "Failed to get on system bus\n");
> +             return 0;
> +     }
> +
> +     msg = dbus_message_new_method_call(busname, path,
> +                                             interface, "notify");
> +     if (msg == NULL) {
> +             dbus_connection_unref(conn);
> +             fprintf(stderr, "Failed to allocate method call\n");
> +             return 0;
> +     }
> +
> +     dbus_message_set_no_reply(msg, TRUE);
> +
> +     dbus_message_append_args(msg,
> +                              DBUS_TYPE_STRING, &reason,
> +                              DBUS_TYPE_INVALID);
> +
> +     dbus_message_iter_init_append(msg, &iter);
> +
> +     dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
> +                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
> +                     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
> +                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
> +
> +     for (envp = environ; envp && *envp; envp++)
> +             append(&dict, *envp);
> +
> +     dbus_message_iter_close_container(&iter, &dict);
> +
> +     if (dbus_connection_send(conn, msg, NULL) == FALSE)
> +             fprintf(stderr, "Failed to send message\n");
> +
> +     dbus_connection_flush(conn);
> +
> +     dbus_message_unref(msg);
> +
> +     dbus_connection_unref(conn);
> +
> +     return 0;
> +}
> diff --git a/src/provider.c b/src/provider.c
> index adad8df..73dfd82 100644
> --- a/src/provider.c
> +++ b/src/provider.c
> @@ -288,23 +288,27 @@ static int set_connected(struct connman_provider 
> *provider,
>               name = connman_inet_ifname(provider->element.index);
>  
>               nameservers = g_strdup(provider->dns);
> -             value = nameservers;
> -             second_ns = strchr(value, ' ');
> -             if (second_ns)
> -                     *(second_ns++) = 0;
> -             __connman_service_append_nameserver(service, value);
> -             value = second_ns;
> -
> -             while (value) {
> -                     char *next = strchr(value, ' ');
> -                     if (next)
> -                             *(next++) = 0;
> -
> -                     connman_resolver_append(name, provider->domain, value);
> -                     value = next;
> +             if (nameservers != NULL) {
> +                     value = nameservers;
> +                     second_ns = strchr(value, ' ');
> +                     if (second_ns)
> +                             *(second_ns++) = 0;
> +                     __connman_service_append_nameserver(service, value);
> +                     value = second_ns;
> +
> +                     while (value) {
> +                             char *next = strchr(value, ' ');
> +                             if (next)
> +                                     *(next++) = 0;
> +
> +                             connman_resolver_append(name, provider->domain,
> +                                                     value);
> +                             value = next;
> +                     }
> +
> +                     g_free(nameservers);
>               }
>  
> -             g_free(nameservers);
>               g_free(name);
>  
>       } else {
> diff --git a/test/connect-openvpn b/test/connect-openvpn
> new file mode 100755
> index 0000000..66bd5fb
> --- /dev/null
> +++ b/test/connect-openvpn
> @@ -0,0 +1,24 @@
> +#!/usr/bin/python
> +
> +import sys
> +import dbus
> +
> +if (len(sys.argv) < 7):
> +     print "Usage: %s <name> <host> <domain> <cafile> <cerfile> <keyfile>" % 
> (sys.argv[0])
> +     sys.exit(1)
> +
> +bus = dbus.SystemBus()
> +
> +manager = dbus.Interface(bus.get_object("org.moblin.connman", "/"),
> +                                     "org.moblin.connman.Manager")
> +
> +print "Attempting to connect service %s" % (sys.argv[1])
> +
> +path = manager.ConnectProvider(({ "Type": "openvpn", "Name": sys.argv[1],
> +                               "Host": sys.argv[2],
> +                               "VPN.Domain": sys.argv[3],
> +                               "OpenVPN.CACert": sys.argv[4],
> +                               "OpenVPN.Cert": sys.argv[5],
> +                               "OpenVPN.Key": sys.argv[6]}))
> +
> +print "VPN service path is %s" %(path)
> -- 
> 1.7.2.3
> 
> _______________________________________________
> connman mailing list
> [email protected]
> http://lists.connman.net/listinfo/connman

-- 
Intel Open Source Technology Centre
http://oss.intel.com/
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to