blob: 75856cd2e170ce39384b6ebe6b0ea841a336984c [file] [log] [blame]
/*
*
* Connection Manager
*
* Copyright (C) 2012 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <errno.h>
#include <getopt.h>
#include <glib.h>
#include <gdbus.h>
#include "services.h"
#include "technology.h"
#include "data_manager.h"
#include "monitor.h"
#include "interactive.h"
#define MANDATORY_ARGS 3
static char *ipv4[] = {
"Method",
"Address",
"Netmask",
"Gateway",
NULL
};
static char *ipv6[] = {
"Method",
"Address",
"PrefixLength",
"Gateway",
"Privacy",
NULL
};
static char *proxy_simple[] = {
"Method",
"URL",
NULL
};
void show_help(void)
{
printf("Usage: connmanctl <command> [args]\n"
" enable Enables given technology\n"
" <technology>\n"
" offlinemode Enables OfflineMode\n"
" disable Disables given technology\n"
" <technology>\n"
" offlinemode Disables OfflineMode\n"
" state Shows if the system is online or offline\n"
" services Display list of all services\n"
" --properties <service name> Show properties of service\n"
" technologies Current technology on the system\n"
" scan <technology> Scans for new services on the given technology\n"
" connect <service> Connect to a given service\n"
" disconnect <service> Disconnect from service\n"
" config <service> [arg] Set certain config options\n"
" --autoconnect=y/n Set autoconnect to service\n"
" --nameservers <names> Set manual name servers\n"
" --timeservers <names> Set manual time servers\n"
" --domains <domains> Set manual domains\n"
" --ipv4 Set ipv4 configuration\n"
" [METHOD|DHCP|AUTO|MANUAL] [IP] [NETMASK] [GATEWAY]\n"
" --ipv6 Set ipv6 configuration\n"
" [METHOD|AUTO|MANUAL|OFF] [IP] [PREFIXLENGTH] [GATEWAY]\n"
" [PRIVACY|DISABLED|ENABLED|PREFERED]\n"
" --proxy Set proxy configuration\n"
" [METHOD|URL|SERVERS|EXCLUDES]\n"
" if METHOD = manual, enter 'servers' then the list of servers\n"
" then enter 'excludes' then the list of excludes\n"
" --remove Remove the service from favorite\n"
" monitor Monitor signals from all Connman interfaces\n"
" --services Monitor signals from the Service interface\n"
" --tech Monitor signals from the Technology interface\n"
" --manager Monitor signals from the Manager interface\n"
" help, --help, (no arguments) Show this dialogue\n"
" exit, quit, q Quit interactive mode\n"
"\nNote: arguments and output are considered EXPERIMENTAL for now.\n\n");
}
int service_switch(int argc, char *argv[], int c, DBusConnection *conn,
struct service_data *service)
{
const char *name;
DBusMessage *message;
int error = 0;
message = get_message(conn, "GetServices");
if (message == NULL)
return -ENOMEM;
switch (c) {
case 'p':
name = find_service(conn, message, argv[2], service);
if (name == NULL) {
error = -ENXIO;
break;
}
error = list_properties(conn, "GetServices", (char *) name);
break;
default:
fprintf(stderr, "Command not recognized, please check help\n");
error = -EINVAL;
break;
}
dbus_message_unref(message);
return error;
}
int config_switch(int argc, char *argv[], int c, DBusConnection *conn)
{
DBusMessage *message;
int num_args = argc - MANDATORY_ARGS;
int error = 0;
dbus_bool_t val;
message = get_message(conn, "GetServices");
if (message == NULL)
return -ENOMEM;
switch (c) {
case 'a':
switch (*optarg) {
case 'y':
case '1':
case 't':
val = TRUE;
break;
case 'n':
case '0':
case 'f':
val = FALSE;
break;
default:
return -EINVAL;
}
error = set_service_property(conn, message, argv[1],
"AutoConnect", NULL,
&val, 0);
break;
case 'i':
error = set_service_property(conn, message, argv[1],
"IPv4.Configuration", ipv4,
argv + MANDATORY_ARGS, num_args);
break;
case 'v':
error = set_service_property(conn, message, argv[1],
"IPv6.Configuration", ipv6,
argv + MANDATORY_ARGS, num_args);
break;
case 'n':
error = set_service_property(conn, message, argv[1],
"Nameservers.Configuration", NULL,
argv + MANDATORY_ARGS, num_args);
break;
case 't':
error = set_service_property(conn, message, argv[1],
"Timeservers.Configuration", NULL,
argv + MANDATORY_ARGS, num_args);
break;
case 'd':
error = set_service_property(conn, message, argv[1],
"Domains.Configuration", NULL,
argv + MANDATORY_ARGS, num_args);
break;
case 'x':
if ((strcmp(argv[3], "direct") == 0 && argc < 5) ||
(strcmp(argv[3], "auto") == 0 && argc < 6)) {
error = set_service_property(conn, message, argv[1],
"Proxy.Configuration", proxy_simple,
argv + MANDATORY_ARGS, num_args);
} else if (strcmp(argv[3], "manual") == 0
&& strcmp(argv[4], "servers") == 0
&& argc > 5) {
argc -= 5;
error = store_proxy_input(conn, message, argv[1],
argc, &argv[5]);
} else {
fprintf(stderr, "Incorrect arguments\n");
error = -EINVAL;
}
break;
case 'r':
error = remove_service(conn, message, argv[1]);
break;
default:
fprintf(stderr, "Command not recognized, please check help\n");
error = -EINVAL;
break;
}
dbus_message_unref(message);
return error;
}
int monitor_switch(int argc, char *argv[], int c, DBusConnection *conn)
{
int error;
switch (c) {
case 's':
error = monitor_connman(conn, "Service", "PropertyChanged");
if (error != 0)
return error;
if (dbus_connection_add_filter(conn, service_property_changed,
NULL, NULL) == FALSE)
return -ENOMEM;
printf("Now monitoring the service interface.\n");
break;
case 'c':
error = monitor_connman(conn, "Technology", "PropertyChanged");
if (error != 0)
return error;
if (dbus_connection_add_filter(conn, tech_property_changed,
NULL, NULL) == FALSE)
return -ENOMEM;
printf("Now monitoring the technology interface.\n");
break;
case 'm':
error = monitor_connman(conn, "Manager", "PropertyChanged");
if (error != 0)
return error;
error = monitor_connman(conn, "Manager", "TechnologyAdded");
if (error != 0)
return error;
error = monitor_connman(conn, "Manager", "TechnologyRemoved");
if (error != 0)
return error;
error = monitor_connman(conn, "Manager", "ServicesChanged");
if (error != 0)
return error;
if (dbus_connection_add_filter(conn, manager_property_changed,
NULL, NULL) == FALSE)
return -ENOMEM;
if (dbus_connection_add_filter(conn, tech_added_removed,
NULL, NULL) == FALSE)
return -ENOMEM;
if (dbus_connection_add_filter(conn, manager_services_changed,
NULL, NULL) == FALSE)
return -ENOMEM;
printf("Now monitoring the manager interface.\n");
break;
default:
fprintf(stderr, "Command not recognized, please check help\n");
return -EINVAL;
break;
}
return 0;
}
int commands_no_options(DBusConnection *connection, char *argv[], int argc)
{
DBusMessage *message = NULL;
int error = 0;
if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "help") == 0 ||
strcmp(argv[0], "h") == 0) {
show_help();
} else if (strcmp(argv[0], "state") == 0) {
if (argc != 1) {
fprintf(stderr, "State cannot accept an argument, "
"see help\n");
error = -EINVAL;
} else
error = list_properties(connection,
"GetProperties", NULL);
} else if (strcmp(argv[0], "technologies") == 0) {
if (argc != 1) {
fprintf(stderr, "Tech cannot accept an argument, "
"see help\n");
error = -EINVAL;
} else
error = list_properties(connection,
"GetTechnologies", NULL);
} else if (strcmp(argv[0], "connect") == 0) {
if (argc != 2) {
fprintf(stderr, "Connect requires a service name or "
"path, see help\n");
error = -EINVAL;
} else
error = connect_service(connection,
strip_service_path(argv[1]));
if (error == 0)
printf("Connected to: %s\n",
strip_service_path(argv[1]));
} else if (strcmp(argv[0], "disconnect") == 0) {
if (argc != 2) {
fprintf(stderr, "Disconnect requires a service name or "
"path, see help\n");
error = -EINVAL;
} else
error = disconnect_service(connection,
strip_service_path(argv[1]));
if (error == 0)
printf("Disconnected from: %s\n",
strip_service_path(argv[1]));
} else if (strcmp(argv[0], "scan") == 0) {
if (argc != 2) {
fprintf(stderr, "Scan requires a service name or path, "
"see help\n");
error = -EINVAL;
}
message = get_message(connection, "GetTechnologies");
if (message == NULL)
error = -ENOMEM;
else
error = scan_technology(connection, message, argv[1]);
} else if (strcmp(argv[0], "enable") == 0) {
if (argc != 2) {
fprintf(stderr, "Enable requires a technology name or "
"the argument 'offlinemode', see help\n");
error = -EINVAL;
} else if (strcmp(argv[1], "offlinemode") == 0) {
error = set_manager(connection, "OfflineMode", TRUE);
if (error == 0)
printf("OfflineMode is now enabled\n");
} else {
message = get_message(connection, "GetTechnologies");
if (message == NULL)
error = -ENOMEM;
else
error = set_technology(connection, message,
"Powered", argv[1], TRUE);
if (error == 0)
printf("Enabled %s technology\n", argv[1]);
}
} else if (strcmp(argv[0], "disable") == 0) {
if (argc != 2) {
fprintf(stderr, "Disable requires a technology name or "
"the argument 'offlinemode' see help\n");
error = -EINVAL;
} else if (strcmp(argv[1], "offlinemode") == 0) {
error = set_manager(connection, "OfflineMode", FALSE);
if (error == 0)
printf("OfflineMode is now disabled\n");
} else {
message = get_message(connection, "GetTechnologies");
if (message == NULL)
error = -ENOMEM;
else
error = set_technology(connection, message,
"Powered", argv[1], FALSE);
if (error == 0)
printf("Disabled %s technology\n", argv[1]);
}
} else
return -1;
if (message != NULL)
dbus_message_unref(message);
return error;
}
int commands_options(DBusConnection *connection, char *argv[], int argc)
{
int error, c;
int option_index = 0;
struct service_data service;
static struct option service_options[] = {
{"properties", required_argument, 0, 'p'},
{0, 0, 0, 0}
};
static struct option config_options[] = {
{"nameservers", required_argument, 0, 'n'},
{"timeservers", required_argument, 0, 't'},
{"domains", required_argument, 0, 'd'},
{"ipv6", required_argument, 0, 'v'},
{"proxy", required_argument, 0, 'x'},
{"autoconnect", required_argument, 0, 'a'},
{"ipv4", required_argument, 0, 'i'},
{"remove", 0, 0, 'r'},
{0, 0, 0, 0}
};
static struct option monitor_options[] = {
{"services", no_argument, 0, 's'},
{"tech", no_argument, 0, 'c'},
{"manager", no_argument, 0, 'm'},
{0, 0, 0, 0}
};
if (strcmp(argv[0], "services") == 0) {
if (argc > 3) {
fprintf(stderr, "Too many arguments for services, "
"see help\n");
return -EINVAL;
}
if (argc < 2) {
printf("List of all services:\n");
error = list_properties(connection, "GetServices", NULL);
if (error != 0)
return error;
} else {
while ((c = getopt_long(argc, argv, "", service_options,
&option_index))) {
if (c == -1) {
if (option_index == 0) {
printf("Services takes an "
"option, see help.\n");
return -EINVAL;
}
break;
}
error = service_switch(argc, argv, c,
connection,
&service);
if (error != 0)
return error;
option_index++;
}
}
} else if (strcmp(argv[0], "config") == 0) {
if (argc < 3) {
fprintf(stderr, "Config requires an option, "
"see help\n");
return -EINVAL;
}
while ((c = getopt_long(argc, argv, "", config_options,
&option_index))) {
if (c == -1) {
if (option_index == 0) {
printf("Config requires an option, "
"see help\n");
return -EINVAL;
}
break;
}
error = config_switch(argc, argv, c, connection);
if (error != 0)
return error;
option_index++;
}
} else if (strcmp(argv[0], "monitor") == 0) {
if (argc > 2) {
fprintf(stderr, "Too many arguments for monitor, "
"see help\n");
return -EINVAL;
}
if (argc < 2) {
error = monitor_connman(connection, "Service",
"PropertyChanged");
if (error != 0)
return error;
error = monitor_connman(connection, "Technology",
"PropertyChanged");
if (error != 0)
return error;
error = monitor_connman(connection, "Manager",
"PropertyChanged");
if (error != 0)
return error;
error = monitor_connman(connection, "Manager",
"TechnologyAdded");
if (error != 0)
return error;
error = monitor_connman(connection, "Manager",
"TechnologyRemoved");
if (error != 0)
return error;
error = monitor_connman(connection, "Manager",
"ServicesChanged");
if (error != 0)
return error;
if (dbus_connection_add_filter(connection,
service_property_changed, NULL, NULL)
== FALSE)
return -ENOMEM;
if (dbus_connection_add_filter(connection,
tech_property_changed, NULL, NULL)
== FALSE)
return -ENOMEM;
if (dbus_connection_add_filter(connection,
tech_added_removed, NULL, NULL)
== FALSE)
return -ENOMEM;
if (dbus_connection_add_filter(connection,
manager_property_changed, NULL, NULL)
== FALSE)
return -ENOMEM;
if (dbus_connection_add_filter(connection,
manager_services_changed, NULL, NULL)
== FALSE)
return -ENOMEM;
printf("Now monitoring all interfaces.\n");
} else
while ((c = getopt_long(argc, argv, "", monitor_options,
&option_index))) {
if (c == -1) {
if (option_index == 0) {
printf("Monitor takes an "
"option, see help\n");
return -EINVAL;
}
break;
}
error = monitor_switch(argc, argv, c, connection);
if (error != 0)
return error;
option_index++;
}
} else
return -1;
return 0;
}