summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorMohamed Abbas <mabbas@linux.intel.com>2011-11-15 13:06:17 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2011-11-15 13:41:44 +0100
commitc28ae08de983d1e88c438a63a291fb4fa9de6bb2 (patch)
tree384d4aa25eb6d1139f3721aa4fc588d9e0fc5431 /scripts
parente07f85f0224699d3ce55cbbda10b05e17dd18253 (diff)
downloadconnman-c28ae08de983d1e88c438a63a291fb4fa9de6bb2.tar.gz
connman-c28ae08de983d1e88c438a63a291fb4fa9de6bb2.tar.bz2
connman-c28ae08de983d1e88c438a63a291fb4fa9de6bb2.zip
pptp: Add ppp plugin library
pppd will use this library to talk with connman vpn plugin. Original patch comes from Mohamed Abbas. Prepared for inclusion by Jukka Rissanen, also changed the pptp function prefix to ppp as the plugin is used by both pptp and l2tp plugins.
Diffstat (limited to 'scripts')
-rw-r--r--scripts/libppp-plugin.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/scripts/libppp-plugin.c b/scripts/libppp-plugin.c
new file mode 100644
index 00000000..ba79db07
--- /dev/null
+++ b/scripts/libppp-plugin.c
@@ -0,0 +1,307 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2011 Intel Corporation. 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pppd/pppd.h>
+#include <pppd/fsm.h>
+#include <pppd/ipcp.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <dbus/dbus.h>
+
+#define INET_ADDRES_LEN (INET_ADDRSTRLEN + 5)
+#define INET_DNS_LEN (2*INET_ADDRSTRLEN + 9)
+
+static char *busname;
+static char *interface;
+static char *path;
+
+static DBusConnection *connection;
+
+char pppd_version[] = VERSION;
+
+int plugin_init(void);
+
+static void append(DBusMessageIter *dict, const char *key, const char *value)
+{
+ DBusMessageIter entry;
+
+ /* We clean the environment before invoking pppd, but
+ * might as well still filter out the few things that get
+ * added that we're not interested in
+ */
+ if (!strcmp(key, "PWD") || !strcmp(key, "_") ||
+ !strcmp(key, "SHLVL") ||
+ !strcmp(key, "connman_busname") ||
+ !strcmp(key, "connman_network"))
+ return;
+
+ 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);
+}
+
+
+static int ppp_have_secret()
+{
+ return 1;
+}
+
+static int ppp_get_secret(char *username, char *password)
+{
+ DBusMessage *msg, *reply;
+ const char *user, *pass;
+ DBusError err;
+
+ if (username == NULL && password == NULL)
+ return -1;
+
+ if (password == NULL)
+ return 1;
+
+ if (connection == NULL)
+ return -1;
+
+ dbus_error_init(&err);
+
+ msg = dbus_message_new_method_call(busname, path, interface, "getsec");
+ if (msg == NULL)
+ return -1;
+
+ dbus_message_append_args(msg, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID);
+
+ reply = dbus_connection_send_with_reply_and_block(connection,
+ msg, -1, &err);
+ if (reply == NULL) {
+ if (dbus_error_is_set(&err) == TRUE)
+ dbus_error_free(&err);
+
+ dbus_message_unref(msg);
+ return -1;
+ }
+
+ dbus_message_unref(msg);
+
+ dbus_error_init(&err);
+
+ if (dbus_message_get_args(reply, &err, DBUS_TYPE_STRING, &user,
+ DBUS_TYPE_STRING, &pass,
+ DBUS_TYPE_INVALID) == FALSE) {
+ if (dbus_error_is_set(&err) == TRUE)
+ dbus_error_free(&err);
+
+ dbus_message_unref(reply);
+ return -1;
+ }
+
+ if (username != NULL)
+ strcpy(username, user);
+
+ strcpy(password, pass);
+
+ dbus_message_unref(reply);
+
+ return 1;
+}
+
+static void ppp_up(void *data, int arg)
+{
+ char buf[INET_ADDRES_LEN];
+ char dns[INET_DNS_LEN];
+ const char *reason = "connect";
+ bool add_blank = FALSE;
+ DBusMessageIter iter, dict;
+ DBusMessage *msg;
+
+ if (connection == NULL)
+ return;
+
+ if (ipcp_gotoptions[0].ouraddr == 0)
+ return;
+
+ msg = dbus_message_new_method_call(busname, path,
+ interface, "notify");
+ if (msg == NULL)
+ return;
+
+ 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);
+
+ append(&dict, "INTERNAL_IFNAME", ifname);
+
+ inet_ntop(AF_INET, &ipcp_gotoptions[0].ouraddr, buf, INET_ADDRSTRLEN);
+ append(&dict, "INTERNAL_IP4_ADDRESS", buf);
+
+ strcpy(buf, "255.255.255.255");
+ append(&dict, "INTERNAL_IP4_NETMASK", buf);
+
+ if (ipcp_gotoptions[0].dnsaddr[0] || ipcp_gotoptions[0].dnsaddr[1]) {
+ memset(dns, 0, sizeof(dns));
+ dns[0] = '\0';
+
+ if (ipcp_gotoptions[0].dnsaddr[0]) {
+ inet_ntop(AF_INET, &ipcp_gotoptions[0].dnsaddr[0],
+ buf, INET_ADDRSTRLEN);
+ strcat(dns, buf);
+
+ add_blank = TRUE;
+ }
+
+ if (ipcp_gotoptions[0].dnsaddr[1]) {
+ inet_ntop(AF_INET, &ipcp_gotoptions[0].dnsaddr[1],
+ buf, INET_ADDRSTRLEN);
+ if (add_blank == TRUE)
+ strcat(dns, " ");
+
+ strcat(dns, buf);
+ }
+ append(&dict, "INTERNAL_IP4_DNS", dns);
+ }
+
+ append(&dict, "MTU", "1400");
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ dbus_connection_send(connection, msg, NULL);
+
+ dbus_connection_flush(connection);
+
+ dbus_message_unref(msg);
+}
+
+static void ppp_exit(void *data, int arg)
+{
+ if (connection != NULL) {
+ dbus_connection_unref(connection);
+ connection = NULL;
+ }
+
+ if (busname != NULL) {
+ free(busname);
+ busname = NULL;
+ }
+
+ if (interface != NULL) {
+ free(interface);
+ interface = NULL;
+ }
+
+ if (path != NULL) {
+ free(path);
+ path = NULL;
+ }
+}
+
+static void ppp_phase_change(void *data, int arg)
+{
+ const char *reason = "disconnect";
+ DBusMessage *msg;
+
+ if (connection == NULL)
+ return;
+
+ if (arg == PHASE_DEAD || arg == PHASE_DISCONNECT) {
+ msg = dbus_message_new_method_call(busname, path,
+ interface, "notify");
+ if (msg == NULL)
+ return;
+
+ dbus_message_set_no_reply(msg, TRUE);
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID);
+
+ dbus_connection_send(connection, msg, NULL);
+
+ dbus_connection_flush(connection);
+
+ dbus_message_unref(msg);
+ }
+}
+
+int plugin_init(void)
+{
+ DBusError error;
+ static const char *bus, *inter, *p;
+
+ dbus_error_init(&error);
+
+ bus = getenv("CONNMAN_BUSNAME");
+ inter = getenv("CONNMAN_INTERFACE");
+ p = getenv("CONNMAN_PATH");
+
+ if (bus == NULL || inter == NULL || p == NULL)
+ return -1;
+
+ busname = strdup(bus);
+ interface = strdup(inter);
+ path = strdup(p);
+
+ if (busname == NULL || interface == NULL || path == NULL) {
+ ppp_exit(NULL, 0);
+ return -1;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (connection == NULL) {
+ if (dbus_error_is_set(&error) == TRUE)
+ dbus_error_free(&error);
+
+ ppp_exit(NULL, 0);
+ return -1;
+ }
+
+ pap_passwd_hook = ppp_get_secret;
+ chap_passwd_hook = ppp_get_secret;
+
+ chap_check_hook = ppp_have_secret;
+ pap_check_hook = ppp_have_secret;
+
+ add_notifier(&ip_up_notifier, ppp_up, NULL);
+ add_notifier(&phasechange, ppp_phase_change, NULL);
+ add_notifier(&exitnotify, ppp_exit, connection);
+
+ return 0;
+}