| Index: plugins/l2tpipsec.c
|
| diff --git a/plugins/l2tpipsec.c b/plugins/l2tpipsec.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..22d9b71b1c80ed97c0ac05c0bac950562ebb76f5
|
| --- /dev/null
|
| +++ b/plugins/l2tpipsec.c
|
| @@ -0,0 +1,233 @@
|
| +/*
|
| + * L2TP/IPsec VPN plugin.
|
| + *
|
| + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + *
|
| + */
|
| +
|
| +#ifdef HAVE_CONFIG_H
|
| +#include <config.h>
|
| +#endif
|
| +
|
| +#include <string.h>
|
| +#include <errno.h>
|
| +#include <unistd.h>
|
| +#include <sys/types.h>
|
| +#include <sys/stat.h>
|
| +#include <fcntl.h>
|
| +
|
| +#include <stdio.h>
|
| +#include <net/if.h>
|
| +
|
| +#include <glib.h>
|
| +
|
| +#define CONNMAN_API_SUBJECT_TO_CHANGE
|
| +#include <connman/plugin.h>
|
| +#include <connman/provider.h>
|
| +#include <connman/log.h>
|
| +#include <connman/task.h>
|
| +#include <connman/dbus.h>
|
| +#include <connman/inet.h>
|
| +
|
| +#include "vpn.h"
|
| +
|
| +#define _DBG_VPN(fmt, arg...) DBG(DBG_VPN, fmt, ## arg)
|
| +
|
| +static DBusConnection *connection;
|
| +
|
| +static DBusMessage *li_get_sec(struct connman_task *task,
|
| + DBusMessage *msg, void *user_data)
|
| +{
|
| + const char *user, *passwd;
|
| + struct connman_provider *provider = user_data;
|
| +
|
| + if (dbus_message_get_no_reply(msg) == FALSE) {
|
| + DBusMessage *reply;
|
| +
|
| + user = connman_provider_get_string(provider, "L2TPIPsec.User");
|
| + passwd = connman_provider_get_string(provider,
|
| + "L2TPIPsec.Password");
|
| +
|
| + if (user == NULL || strlen(user) == 0) {
|
| + _DBG_VPN("%s: User not set", __func__);
|
| + return NULL;
|
| + }
|
| + if (passwd == NULL || strlen(passwd) == 0) {
|
| + _DBG_VPN("%s: Password not set", __func__);
|
| + return NULL;
|
| + }
|
| +
|
| + reply = dbus_message_new_method_return(msg);
|
| + if (reply == NULL)
|
| + return NULL;
|
| +
|
| + dbus_message_append_args(reply, DBUS_TYPE_STRING, &user,
|
| + DBUS_TYPE_STRING, &passwd,
|
| + DBUS_TYPE_INVALID);
|
| +
|
| + return reply;
|
| + }
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +static int li_notify(DBusMessage *msg, struct connman_provider *provider)
|
| +{
|
| + DBusMessageIter iter, dict;
|
| + const char *reason, *key;
|
| + char *value;
|
| + char *ifname = NULL;
|
| + char *dns_servers[3];
|
| + struct connman_ipaddress ipaddr;
|
| +
|
| + dbus_message_iter_init(msg, &iter);
|
| +
|
| + dbus_message_iter_get_basic(&iter, &reason);
|
| + dbus_message_iter_next(&iter);
|
| +
|
| + _DBG_VPN("%s: Reason %s", __func__, reason);
|
| +
|
| + if (provider == NULL) {
|
| + connman_error("%s: No provider found", __func__);
|
| + return VPN_STATE_FAILURE;
|
| + }
|
| +
|
| + if (strcmp(reason, "connect"))
|
| + return VPN_STATE_DISCONNECT;
|
| +
|
| + memset(&ipaddr, 0, sizeof(ipaddr));
|
| + ipaddr.af = AF_INET;
|
| + ipaddr.mask |= CONNMAN_IPCONFIG_AF;
|
| + memset(dns_servers, 0, sizeof(dns_servers));
|
| + ipaddr.dns_servers = dns_servers;
|
| +
|
| + 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_VPN("%s = %s", key, value);
|
| +
|
| + if (!strcmp(key, "INTERNAL_IP4_ADDRESS")) {
|
| + ipaddr.local = value;
|
| + ipaddr.mask |= CONNMAN_IPCONFIG_LOCAL;
|
| + } else if (!strcmp(key, "EXTERNAL_IP4_ADDRESS")) {
|
| + ipaddr.peer = value;
|
| + ipaddr.mask |= CONNMAN_IPCONFIG_PEER;
|
| + } else if (!strcmp(key, "GATEWAY_ADDRESS")) {
|
| + ipaddr.gateway = value;
|
| + ipaddr.mask |= CONNMAN_IPCONFIG_GW;
|
| + } else if (!strcmp(key, "DNS1")) {
|
| + ipaddr.dns_servers[0] = value;
|
| + ipaddr.mask |= CONNMAN_IPCONFIG_DNS;
|
| + } else if (!strcmp(key, "DNS2")) {
|
| + ipaddr.dns_servers[1] = value;
|
| + } else if (!strcmp(key, "INTERNAL_IFNAME")) {
|
| + ifname = value;
|
| + }
|
| +
|
| + dbus_message_iter_next(&dict);
|
| + }
|
| +
|
| + if (vpn_set_ifname(provider, ifname) < 0) {
|
| + g_free(ifname);
|
| + return VPN_STATE_FAILURE;
|
| + }
|
| +
|
| + connman_provider_ipconfig_set(provider, &ipaddr);
|
| +
|
| + return VPN_STATE_CONNECT;
|
| +}
|
| +
|
| +static int li_connect(struct connman_provider *provider,
|
| + struct connman_task *task, const char *if_name)
|
| +{
|
| +#define OPT_STR(property, option) do { \
|
| + const char *s = connman_provider_get_string(provider, property); \
|
| + if (s != NULL) \
|
| + connman_task_add_argument(task, option, (char *)s); \
|
| +} while (0)
|
| +#define OPT_BOOL(property, true_option, false_option) do { \
|
| + const char *s = connman_provider_get_string(provider, property); \
|
| + if (s != NULL) { \
|
| + connman_task_add_argument(task, strcmp("true", s) == 0 ? \
|
| + true_option : false_option, \
|
| + NULL); \
|
| + } \
|
| +} while (0)
|
| + const char *vpnhost;
|
| + int err, fd;
|
| +
|
| + if (connman_task_set_notify(task, "getsec",
|
| + li_get_sec, provider))
|
| + return -ENOMEM;
|
| +
|
| + vpnhost = connman_provider_get_string(provider, "Host");
|
| + if (!vpnhost) {
|
| + connman_error("%s: host not set; cannot enable VPN", __func__);
|
| + return -EINVAL;
|
| + }
|
| +
|
| + connman_task_add_argument(task, "--remote_address",
|
| + (char *)vpnhost);
|
| + connman_task_add_argument(task, "--pppd_plugin",
|
| + SCRIPTDIR "/libppp-plugin.so");
|
| +
|
| + OPT_STR("L2TPIPsec.CACert", "--server_ca_file");
|
| + OPT_STR("L2TPIPsec.Key", "--client_key_file");
|
| + OPT_STR("L2TPIPsec.Cert", "--client_cert_file");
|
| + OPT_STR("L2TPIPsec.PSK", "--psk_file");
|
| + OPT_STR("L2TPIPsec.User", "--user");
|
| + OPT_STR("L2TPIPsec.IPsecTimeout", "--ipsec_timeout");
|
| + OPT_STR("L2TPIPsec.LeftProtoPort", "--leftprotoport");
|
| + OPT_BOOL("L2TPIPsec.PFS", "--pfs", "--nopfs");
|
| + OPT_BOOL("L2TPIPsec.Rekey", "--rekey", "--norekey");
|
| + OPT_STR("L2TPIPsec.RightProtoPort", "--leftprotoport");
|
| +
|
| + OPT_BOOL("L2TPIPsec.RequireChap", "--require_chap",
|
| + "--norequire_chap");
|
| + OPT_BOOL("L2TPIPsec.RefusePap", "--refuse_pap", "--norefuse_pap");
|
| + OPT_BOOL("L2TPIPsec.RequireAuth", "--require_authentication",
|
| + "--norequire_authentication");
|
| + OPT_BOOL("L2TPIPsec.LengthBit", "--length_bit", "--nolength_bit");
|
| +
|
| + fd = fileno(stderr);
|
| + err = connman_task_run(task, vpn_died, provider,
|
| + NULL, &fd, &fd);
|
| + if (err < 0) {
|
| + connman_error("l2tpipsec failed to start");
|
| + return -EIO;
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +static struct vpn_driver vpn_driver = {
|
| + .flags = VPN_FLAG_NO_TUN,
|
| + .notify = li_notify,
|
| + .connect = li_connect,
|
| +};
|
| +
|
| +static int li_init(void)
|
| +{
|
| + connection = connman_dbus_get_connection();
|
| +
|
| + return vpn_register("l2tpipsec", &vpn_driver, L2TPIPSEC);
|
| +}
|
| +
|
| +static void li_exit(void)
|
| +{
|
| + vpn_unregister("l2tpipsec");
|
| +
|
| + dbus_connection_unref(connection);
|
| +}
|
| +
|
| +CONNMAN_PLUGIN_DEFINE(l2tpipsec, "l2tpipsec plugin", VERSION,
|
| + CONNMAN_PLUGIN_PRIORITY_DEFAULT, li_init, li_exit)
|
|
|