Index: plugins/l2tpipsec.c |
diff --git a/plugins/l2tpipsec.c b/plugins/l2tpipsec.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7f1d3e2d2e28aeea5c99c21a8589be123c0e404b |
--- /dev/null |
+++ b/plugins/l2tpipsec.c |
@@ -0,0 +1,220 @@ |
+/* |
+ * 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 || |
+ passwd == NULL || strlen(passwd) == 0) { |
+ _DBG_VPN("User or password not set"); |
+ 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, *value; |
+ char *ifname = NULL; |
+ char *dns1 = NULL; |
+ char *dns2 = NULL; |
+ struct connman_ipaddress ipaddr; |
+ |
+ dbus_message_iter_init(msg, &iter); |
+ |
+ dbus_message_iter_get_basic(&iter, &reason); |
+ dbus_message_iter_next(&iter); |
+ |
+ 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; |
+ |
+ 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 = g_strdup(value); |
+ ipaddr.mask |= CONNMAN_IPCONFIG_LOCAL; |
+ } else if (!strcmp(key, "EXTERNAL_IP4_ADDRESS")) { |
+ ipaddr.peer = g_strdup(value); |
+ ipaddr.mask |= CONNMAN_IPCONFIG_PEER; |
+ } else if (!strcmp(key, "DNS1")) { |
+ dns1 = g_strdup(value); |
+ } else if (!strcmp(key, "DNS2")) { |
+ dns2 = g_strdup(value); |
+ } else if (!strcmp(key, "INTERNAL_IFNAME")) { |
+ ifname = g_strdup(value); |
+ } |
+ |
+ dbus_message_iter_next(&dict); |
+ } |
+ |
+ ipaddr.dns_servers = g_try_new0(gchar *, 3); |
+ if (dns1 != NULL) { |
+ ipaddr.dns_servers[0] = dns1; |
+ if (dns2 != NULL) |
+ ipaddr.dns_servers[1] = dns2; |
+ ipaddr.mask |= CONNMAN_IPCONFIG_DNS; |
+ } |
+ |
+ if (vpn_set_ifname(provider, ifname) <0) { |
+ g_free(ifname); |
+ return VPN_STATE_FAILURE; |
+ } |
+ |
+ connman_provider_ipconfig_set(provider, &ipaddr); |
+ |
+ g_free(ifname); |
+ g_free(dns1); |
+ g_free(dns2); |
+ g_strfreev(ipaddr.dns_servers); /* TODO(kmixter): OK to free? */ |
+ |
+ 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, option) do { \ |
+ const char *s = connman_provider_get_string(provider, property); \ |
+ if (s != NULL) \ |
+ connman_task_add_argument(task, 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", (char *)vpnhost); |
+ // TODO: figure out the local address. |
+ connman_task_add_argument(task, "--local", "172.22.75.194"); |
+ 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"); |
+ |
+ 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) |