*
* ConnMan VPN daemon
*
- * Copyright (C) 2010 BMW Car IT GmbH. All rights reserved.
- * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ * Copyright (C) 2010,2013-2014 BMW Car IT GmbH.
+ * Copyright (C) 2012-2013 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
enum {
OPT_STRING = 1,
OPT_BOOL = 2,
+ OPT_PPTP_ONLY = 3,
};
struct {
const char *cm_opt;
const char *pptp_opt;
- const char *vpnc_default;
+ const char *pptp_default;
int type;
} pptp_options[] = {
{ "PPTP.User", "user", NULL, OPT_STRING },
+ { "PPTP.IdleWait", "--idle-wait", NULL, OPT_PPTP_ONLY},
+ { "PPTP.MaxEchoWait", "--max-echo-wait", NULL, OPT_PPTP_ONLY},
{ "PPPD.EchoFailure", "lcp-echo-failure", "0", OPT_STRING },
{ "PPPD.EchoInterval", "lcp-echo-interval", "0", OPT_STRING },
{ "PPPD.Debug", "debug", NULL, OPT_STRING },
{ "PPPD.RequirMPPE40", "require-mppe-40", NULL, OPT_BOOL },
{ "PPPD.RequirMPPE128", "require-mppe-128", NULL, OPT_BOOL },
{ "PPPD.RequirMPPEStateful", "mppe-stateful", NULL, OPT_BOOL },
- { "PPPD.NoVJ", "no-vj-comp", NULL, OPT_BOOL },
+ { "PPPD.NoVJ", "novj", NULL, OPT_BOOL },
};
static DBusConnection *connection;
struct vpn_provider *provider = user_data;
DBusMessage *reply;
- if (dbus_message_get_no_reply(msg) == TRUE)
+ if (dbus_message_get_no_reply(msg))
return NULL;
user = vpn_provider_get_string(provider, "PPTP.User");
passwd = vpn_provider_get_string(provider, "PPTP.Password");
- if (user == NULL || strlen(user) == 0 ||
- passwd == NULL || strlen(passwd) == 0)
+ if (!user || strlen(user) == 0 ||
+ !passwd || strlen(passwd) == 0)
return NULL;
reply = dbus_message_new_method_return(msg);
- if (reply == NULL)
+ if (!reply)
return NULL;
dbus_message_append_args(reply, DBUS_TYPE_STRING, &user,
dbus_message_iter_get_basic(&iter, &reason);
dbus_message_iter_next(&iter);
- if (provider == NULL) {
+ if (!provider) {
connman_error("No provider found");
return VPN_STATE_FAILURE;
}
- if (strcmp(reason, "auth failed") == 0)
+ if (strcmp(reason, "auth failed") == 0) {
+ DBG("authentication failure");
+
+ vpn_provider_set_string(provider, "PPTP.User", NULL);
+ vpn_provider_set_string_hide_value(provider, "PPTP.Password",
+ NULL);
+
return VPN_STATE_AUTH_FAILURE;
+ }
if (strcmp(reason, "connect"))
return VPN_STATE_DISCONNECT;
DBG("%s = %s", key, value);
- if (!strcmp(key, "INTERNAL_IP4_ADDRESS")) {
- vpn_provider_set_string(provider, "Address", value);
+ if (!strcmp(key, "INTERNAL_IP4_ADDRESS"))
addressv4 = g_strdup(value);
- }
- if (!strcmp(key, "INTERNAL_IP4_NETMASK")) {
- vpn_provider_set_string(provider, "Netmask", value);
+ if (!strcmp(key, "INTERNAL_IP4_NETMASK"))
netmask = g_strdup(value);
- }
- if (!strcmp(key, "INTERNAL_IP4_DNS")) {
- vpn_provider_set_string(provider, "DNS", value);
+ if (!strcmp(key, "INTERNAL_IP4_DNS"))
nameservers = g_strdup(value);
- }
if (!strcmp(key, "INTERNAL_IFNAME"))
ifname = g_strdup(value);
return VPN_STATE_FAILURE;
}
- if (addressv4 != NULL)
+ if (addressv4)
ipaddress = connman_ipaddress_alloc(AF_INET);
g_free(ifname);
- if (ipaddress == NULL) {
+ if (!ipaddress) {
connman_error("No IP address for provider");
g_free(addressv4);
g_free(netmask);
}
value = vpn_provider_get_string(provider, "HostIP");
- if (value != NULL) {
+ if (value) {
vpn_provider_set_string(provider, "Gateway", value);
gateway = g_strdup(value);
}
- if (addressv4 != NULL)
+ if (addressv4)
connman_ipaddress_set_ipv4(ipaddress, addressv4, netmask,
gateway);
+ connman_ipaddress_set_p2p(ipaddress, true);
vpn_provider_set_ipaddress(provider, ipaddress);
vpn_provider_set_nameservers(provider, nameservers);
static int pptp_save(struct vpn_provider *provider, GKeyFile *keyfile)
{
const char *option;
- connman_bool_t pptp_option, pppd_option;
+ bool pptp_option, pppd_option;
int i;
for (i = 0; i < (int)ARRAY_SIZE(pptp_options); i++) {
- pptp_option = pppd_option = FALSE;
+ pptp_option = pppd_option = false;
if (strncmp(pptp_options[i].cm_opt, "PPTP.", 5) == 0)
- pptp_option = TRUE;
+ pptp_option = true;
if (strncmp(pptp_options[i].cm_opt, "PPPD.", 5) == 0)
- pppd_option = TRUE;
+ pppd_option = true;
- if (pptp_option == TRUE || pppd_option == TRUE) {
+ if (pptp_option || pppd_option) {
option = vpn_provider_get_string(provider,
pptp_options[i].cm_opt);
- if (option == NULL) {
+ if (!option) {
/*
* Check if the option prefix is PPTP as the
* PPPD options were using PPTP prefix earlier.
*/
char *pptp_str;
- if (pppd_option == FALSE)
+ if (!pppd_option)
continue;
pptp_str = g_strdup_printf("PPTP.%s",
pptp_str);
g_free(pptp_str);
- if (option == NULL)
+ if (!option)
continue;
}
static void pptp_write_bool_option(struct connman_task *task,
const char *key, const char *value)
{
- if (key != NULL && value != NULL) {
+ if (key && value) {
if (strcasecmp(value, "yes") == 0 ||
strcasecmp(value, "true") == 0 ||
strcmp(value, "1") == 0)
static void request_input_reply(DBusMessage *reply, void *user_data)
{
struct request_input_reply *pptp_reply = user_data;
+ struct pptp_private_data *data;
const char *error = NULL;
char *username = NULL, *password = NULL;
char *key;
DBusMessageIter iter, dict;
+ int err;
DBG("provider %p", pptp_reply->provider);
- if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ if (!reply)
+ goto done;
+
+ data = pptp_reply->user_data;
+
+ err = vpn_agent_check_and_process_reply_error(reply,
+ pptp_reply->provider, data->task, data->cb,
+ data->user_data);
+ if (err) {
+ /* Ensure cb is called only once */
+ data->cb = NULL;
+ data->user_data = NULL;
error = dbus_message_get_error_name(reply);
goto done;
}
- if (vpn_agent_check_reply_has_dict(reply) == FALSE)
+ if (!vpn_agent_check_reply_has_dict(reply))
goto done;
dbus_message_iter_init(reply, &iter);
const char *error, void *user_data);
static int request_input(struct vpn_provider *provider,
- request_cb_t callback, void *user_data)
+ request_cb_t callback, const char *dbus_sender,
+ void *user_data)
{
DBusMessage *message;
const char *path, *agent_sender, *agent_path;
DBusMessageIter dict;
struct request_input_reply *pptp_reply;
int err;
+ void *agent;
- connman_agent_get_info(&agent_sender, &agent_path);
-
- if (provider == NULL || agent_path == NULL || callback == NULL)
+ agent = connman_agent_get_info(dbus_sender, &agent_sender,
+ &agent_path);
+ if (!provider || !agent || !agent_path || !callback)
return -ESRCH;
message = dbus_message_new_method_call(agent_sender, agent_path,
VPN_AGENT_INTERFACE,
"RequestInput");
- if (message == NULL)
+ if (!message)
return -ENOMEM;
dbus_message_iter_init_append(message, &iter);
connman_dbus_dict_open(&iter, &dict);
+ if (vpn_provider_get_authentication_errors(provider))
+ vpn_agent_append_auth_failure(&dict, provider, NULL);
+
vpn_agent_append_user_info(&dict, provider, "PPTP.User");
vpn_agent_append_host_and_name(&dict, provider);
connman_dbus_dict_close(&iter, &dict);
pptp_reply = g_try_new0(struct request_input_reply, 1);
- if (pptp_reply == NULL) {
+ if (!pptp_reply) {
dbus_message_unref(message);
return -ENOMEM;
}
err = connman_agent_queue_message(provider, message,
connman_timeout_input_request(),
- request_input_reply, pptp_reply);
+ request_input_reply, pptp_reply, agent);
if (err < 0 && err != -EBUSY) {
DBG("error %d sending agent request", err);
dbus_message_unref(message);
vpn_provider_connect_cb_t cb, void *user_data,
const char *username, const char *password)
{
- const char *opt_s, *host;
+ GString *pptp_opt_s;
+ const char *opt_s;
+ const char *host;
char *str;
int err, i;
- host = vpn_provider_get_string(provider, "Host");
- if (host == NULL) {
- connman_error("Host not set; cannot enable VPN");
- err = -EINVAL;
- goto done;
- }
-
- if (username == NULL || password == NULL) {
+ if (!username || !password) {
DBG("Cannot connect username %s password %p",
username, password);
err = -EINVAL;
goto done;
}
- vpn_provider_set_string(provider, "PPTP.User", username);
- vpn_provider_set_string(provider, "PPTP.Password", password);
-
DBG("username %s password %p", username, password);
- str = g_strdup_printf("%s %s --nolaunchpppd --loglevel 2",
- PPTP, host);
- if (str == NULL) {
- connman_error("can not allocate memory");
- err = -ENOMEM;
- goto done;
- }
+ host = vpn_provider_get_string(provider, "Host");
- connman_task_add_argument(task, "pty", str);
- g_free(str);
+ /* Create PPTP options for pppd "pty" */
+ pptp_opt_s = g_string_new(NULL);
+ g_string_append_printf(pptp_opt_s, "%s %s --nolaunchpppd --loglevel 2",
+ PPTP, host);
connman_task_add_argument(task, "nodetach", NULL);
connman_task_add_argument(task, "lock", NULL);
+ connman_task_add_argument(task, "logfd", "2");
connman_task_add_argument(task, "usepeerdns", NULL);
connman_task_add_argument(task, "noipdefault", NULL);
connman_task_add_argument(task, "noauth", NULL);
for (i = 0; i < (int)ARRAY_SIZE(pptp_options); i++) {
opt_s = vpn_provider_get_string(provider,
pptp_options[i].cm_opt);
- if (opt_s == NULL)
- opt_s = pptp_options[i].vpnc_default;
+ if (!opt_s)
+ opt_s = pptp_options[i].pptp_default;
- if (opt_s == NULL)
+ if (!opt_s)
continue;
if (pptp_options[i].type == OPT_STRING)
else if (pptp_options[i].type == OPT_BOOL)
pptp_write_bool_option(task,
pptp_options[i].pptp_opt, opt_s);
+ else if (pptp_options[i].type == OPT_PPTP_ONLY)
+ g_string_append_printf(pptp_opt_s, " %s %s",
+ pptp_options[i].pptp_opt, opt_s);
}
+ str = g_string_free(pptp_opt_s, FALSE);
+ connman_task_add_argument(task, "pty", str);
+ g_free(str);
+
connman_task_add_argument(task, "plugin",
SCRIPTDIR "/libppp-plugin.so");
}
done:
- if (cb != NULL)
+ if (cb)
cb(provider, user_data, err);
return err;
{
struct pptp_private_data *data = user_data;
- if (username == NULL || password == NULL)
+ if (!username || !password)
DBG("Requesting username %s or password failed, error %s",
username, error);
- else if (error != NULL)
+ else if (error)
DBG("error %s", error);
+ vpn_provider_set_string(provider, "PPTP.User", username);
+ vpn_provider_set_string_hide_value(provider, "PPTP.Password",
+ password);
+
run_connect(provider, data->task, data->if_name, data->cb,
data->user_data, username, password);
static int pptp_connect(struct vpn_provider *provider,
struct connman_task *task, const char *if_name,
- vpn_provider_connect_cb_t cb, void *user_data)
+ vpn_provider_connect_cb_t cb, const char *dbus_sender,
+ void *user_data)
{
const char *username, *password;
int err;
DBG("user %s password %p", username, password);
- if (username == NULL || password == NULL) {
+ if (!username || !password) {
struct pptp_private_data *data;
data = g_try_new0(struct pptp_private_data, 1);
- if (data == NULL)
+ if (!data)
return -ENOMEM;
data->task = task;
data->cb = cb;
data->user_data = user_data;
- err = request_input(provider, request_input_cb, data);
+ err = request_input(provider, request_input_cb, dbus_sender,
+ data);
if (err != -EINPROGRESS) {
free_private_data(data);
goto done;
username, password);
error:
- if (cb != NULL)
+ if (cb)
cb(provider, user_data, err);
return err;
}
-static int pptp_error_code(int exit_code)
+static int pptp_error_code(struct vpn_provider *provider, int exit_code)
{
switch (exit_code) {
static void pptp_disconnect(struct vpn_provider *provider)
{
- vpn_provider_set_string(provider, "PPTP.Password", NULL);
+ if (!provider)
+ return;
+
+ vpn_provider_set_string_hide_value(provider, "PPTP.Password", NULL);
+
+ connman_agent_cancel(provider);
}
static struct vpn_driver vpn_driver = {