network-manager.c 29.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* nmcli - command-line tool to control NetworkManager
 *
 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
17
 * (C) Copyright 2010 - 2014 Red Hat, Inc.
18 19
 */

20 21
#include "config.h"

22 23 24 25 26 27 28 29 30 31 32
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <glib.h>
#include <glib/gi18n.h>

#include "utils.h"
#include "network-manager.h"


33
/* Available fields for 'general status' */
34
static NmcOutputField nmc_fields_nm_status[] = {
Dan Winship's avatar
Dan Winship committed
35 36 37
	{"RUNNING",      N_("RUNNING"),      15},  /* 0 */
	{"VERSION",      N_("VERSION"),      10},  /* 1 */
	{"STATE",        N_("STATE"),        15},  /* 2 */
38 39 40 41 42 43 44 45 46
	{"STARTUP",      N_("STARTUP"),      10},  /* 3 */
	{"CONNECTIVITY", N_("CONNECTIVITY"), 15},  /* 4 */
	{"NETWORKING",   N_("NETWORKING"),   13},  /* 5 */
	{"WIFI-HW",      N_("WIFI-HW"),      15},  /* 6 */
	{"WIFI",         N_("WIFI"),         10},  /* 7 */
	{"WWAN-HW",      N_("WWAN-HW"),      15},  /* 8 */
	{"WWAN",         N_("WWAN"),         10},  /* 9 */
	{"WIMAX-HW",     N_("WIMAX-HW"),     15},  /* 10 */
	{"WIMAX",        N_("WIMAX"),        10},  /* 11 */
Dan Winship's avatar
Dan Winship committed
47
	{NULL,           NULL,                0}
48
};
49
#if WITH_WIMAX
50
#define NMC_FIELDS_NM_STATUS_ALL     "RUNNING,VERSION,STATE,STARTUP,CONNECTIVITY,NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN,WIMAX-HW,WIMAX"
51
#define NMC_FIELDS_NM_STATUS_SWITCH  "NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN,WIMAX-HW,WIMAX"
52
#define NMC_FIELDS_NM_STATUS_RADIO   "WIFI-HW,WIFI,WWAN-HW,WWAN,WIMAX-HW,WIMAX"
53
#else
54
#define NMC_FIELDS_NM_STATUS_ALL     "RUNNING,VERSION,STATE,STARTUP,CONNECTIVITY,NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
55
#define NMC_FIELDS_NM_STATUS_SWITCH  "NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
56
#define NMC_FIELDS_NM_STATUS_RADIO   "WIFI-HW,WIFI,WWAN-HW,WWAN"
57
#endif
Dan Winship's avatar
Dan Winship committed
58
#define NMC_FIELDS_NM_STATUS_COMMON  "STATE,CONNECTIVITY,WIFI-HW,WIFI,WWAN-HW,WWAN"
59
#define NMC_FIELDS_NM_NETWORKING     "NETWORKING"
60 61
#define NMC_FIELDS_NM_WIFI           "WIFI"
#define NMC_FIELDS_NM_WWAN           "WWAN"
62
#define NMC_FIELDS_NM_WIMAX          "WIMAX"
Dan Winship's avatar
Dan Winship committed
63
#define NMC_FIELDS_NM_CONNECTIVITY   "CONNECTIVITY"
64

65 66

/* Available fields for 'general permissions' */
67
static NmcOutputField nmc_fields_nm_permissions[] = {
68 69 70
	{"PERMISSION", N_("PERMISSION"), 57},  /* 0 */
	{"VALUE",      N_("VALUE"),      10},  /* 1 */
	{NULL,         NULL,              0}
71 72 73 74
};
#define NMC_FIELDS_NM_PERMISSIONS_ALL     "PERMISSION,VALUE"
#define NMC_FIELDS_NM_PERMISSIONS_COMMON  "PERMISSION,VALUE"

75 76
/* Available fields for 'general logging' */
static NmcOutputField nmc_fields_nm_logging[] = {
77 78 79
	{"LEVEL",   N_("LEVEL"),   10},  /* 0 */
	{"DOMAINS", N_("DOMAINS"), 70},  /* 1 */
	{NULL,      NULL,           0}
80 81 82 83
};
#define NMC_FIELDS_NM_LOGGING_ALL     "LEVEL,DOMAINS"
#define NMC_FIELDS_NM_LOGGING_COMMON  "LEVEL,DOMAINS"

84

85
/* glib main loop variable - defined in nmcli.c */
86 87
extern GMainLoop *loop;

88

89
static void
90
usage_general (void)
91 92
{
	fprintf (stderr,
93
	         _("Usage: nmcli general { COMMAND | help }\n\n"
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
	           "COMMAND := { status | hostname | permissions | logging }\n\n"
	           "  status\n\n"
	           "  hostname [<hostname>]\n\n"
	           "  permissions\n\n"
	           "  logging [level <log level>] [domains <log domains>]\n\n"));
}

static void
usage_general_status (void)
{
	fprintf (stderr,
	         _("Usage: nmcli general status { help }\n"
	           "\n"
	           "Show overall status of NetworkManager.\n"
	           "'status' is the default action, which means 'nmcli gen' calls 'nmcli gen status'\n\n"));
}

static void
usage_general_hostname (void)
{
	fprintf (stderr,
	         _("Usage: nmcli general hostname { ARGUMENTS | help }\n"
	           "\n"
	           "ARGUMENTS := [<hostname>]\n"
	           "\n"
	           "Get or change persistent system hostname.\n"
	           "With no arguments, this prints currently configured hostname. When you pass\n"
	           "a hostname, NetworkManager will set it as the new persistent system hostname.\n\n"));
}

static void
usage_general_permissions (void)
{
	fprintf (stderr,
	         _("Usage: nmcli general permissions { help }\n"
	           "\n"
	           "Show caller permissions for authenticated operations.\n\n"));
}

static void
usage_general_logging (void)
{
	fprintf (stderr,
	         _("Usage: nmcli general logging { ARGUMENTS | help }\n"
	           "\n"
	           "ARGUMENTS := [level <log level>] [domains <log domains>]\n"
	           "\n"
	           "Get or change NetworkManager logging level and domains.\n"
	           "Without any argument current logging level and domains are shown. In order to\n"
	           "change logging state, provide level and/or domain. Please refer to the man page\n"
	           "for the list of possible logging domains.\n\n"));
145 146 147
}

static void
148
usage_networking (void)
149 150
{
	fprintf (stderr,
151
	         _("Usage: nmcli networking { COMMAND | help }\n\n"
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
	           "COMMAND := { [ on | off | connectivity ] }\n\n"
	           "  on\n\n"
	           "  off\n\n"
	           "  connectivity [check]\n\n"));
}

static void
usage_networking_on (void)
{
	fprintf (stderr,
	         _("Usage: nmcli networking on { help }\n"
	           "\n"
	           "Switch networking on.\n\n"));
}

static void
usage_networking_off (void)
{
	fprintf (stderr,
	         _("Usage: nmcli networking off { help }\n"
	           "\n"
	           "Switch networking off.\n\n"));
}

static void
usage_networking_connectivity (void)
{
	fprintf (stderr,
	         _("Usage: nmcli networking connectivity { ARGUMENTS | help }\n"
	           "\n"
	           "ARGUMENTS := [check]\n"
	           "\n"
	           "Get network connectivity state.\n"
	           "The optional 'check' argument makes NetworkManager re-check the connectivity.\n\n"));

187 188 189 190 191 192 193
}

static void
usage_radio (void)
{
	fprintf (stderr,
	         _("Usage: nmcli radio { COMMAND | help }\n\n"
194
#if WITH_WIMAX
195 196
	           "COMMAND := { all | wifi | wwan | wimax }\n\n"
	           "  all | wifi | wwan | wimax [ on | off ]\n\n"
197
#else
198 199
	           "COMMAND := { all | wifi | wwan }\n\n"
	           "  all | wifi | wwan [ on | off ]\n\n"
200 201
#endif
	         ));
202 203
}

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
static void
usage_radio_all (void)
{
	fprintf (stderr,
	         _("Usage: nmcli radio all { ARGUMENTS | help }\n"
	           "\n"
	           "ARGUMENTS := [on | off]\n"
	           "\n"
	           "Get status of all radio switches, or turn them on/off.\n\n"));
}

static void
usage_radio_wifi (void)
{
	fprintf (stderr,
	         _("Usage: nmcli radio wifi { ARGUMENTS | help }\n"
	           "\n"
	           "ARGUMENTS := [on | off]\n"
	           "\n"
	           "Get status of Wi-Fi radio switch, or turn it on/off.\n\n"));
}

static void
usage_radio_wwan (void)
{
	fprintf (stderr,
	         _("Usage: nmcli radio wwan { ARGUMENTS | help }\n"
	           "\n"
	           "ARGUMENTS := [on | off]\n"
	           "\n"
	           "Get status of mobile broadband radio switch, or turn it on/off.\n\n"));
}

#if WITH_WIMAX
static void
usage_radio_wimax (void)
{
	fprintf (stderr,
	         _("Usage: nmcli radio wimax { ARGUMENTS | help }\n"
	           "\n"
	           "ARGUMENTS := [on | off]\n"
	           "\n"
	           "Get status of WiMAX radio switch, or turn it on/off.\n\n"));
}
#endif

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
/* quit main loop */
static void
quit (void)
{
	g_main_loop_quit (loop);  /* quit main loop */
}

static const char *
nm_state_to_string (NMState state)
{
	switch (state) {
	case NM_STATE_ASLEEP:
		return _("asleep");
	case NM_STATE_CONNECTING:
		return _("connecting");
265 266 267 268 269
	case NM_STATE_CONNECTED_LOCAL:
		return _("connected (local only)");
	case NM_STATE_CONNECTED_SITE:
		return _("connected (site only)");
	case NM_STATE_CONNECTED_GLOBAL:
270
		return _("connected");
271 272
	case NM_STATE_DISCONNECTING:
		return _("disconnecting");
273 274 275 276 277 278 279 280
	case NM_STATE_DISCONNECTED:
		return _("disconnected");
	case NM_STATE_UNKNOWN:
	default:
		return _("unknown");
	}
}

Dan Winship's avatar
Dan Winship committed
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
static const char *
nm_connectivity_to_string (NMConnectivityState connectivity)
{
	switch (connectivity) {
	case NM_CONNECTIVITY_NONE:
		return _("none");
	case NM_CONNECTIVITY_PORTAL:
		return _("portal");
	case NM_CONNECTIVITY_LIMITED:
		return _("limited");
	case NM_CONNECTIVITY_FULL:
		return _("full");
	case NM_CONNECTIVITY_UNKNOWN:
	default:
		return _("unknown");
	}
}

299
static gboolean
300
show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_flds)
301
{
302
	gboolean nm_running, startup = FALSE;
303
	NMState state = NM_STATE_UNKNOWN;
Dan Winship's avatar
Dan Winship committed
304
	NMConnectivityState connectivity = NM_CONNECTIVITY_UNKNOWN;
305
	const char *net_enabled_str;
306 307
	const char *wireless_hw_enabled_str, *wireless_enabled_str;
	const char *wwan_hw_enabled_str, *wwan_enabled_str;
308
#if WITH_WIMAX
309
	const char *wimax_hw_enabled_str, *wimax_enabled_str;
310
#endif
311 312
	GError *error = NULL;
	const char *fields_str;
313 314
	const char *fields_all =    print_flds ? print_flds : NMC_FIELDS_NM_STATUS_ALL;
	const char *fields_common = print_flds ? print_flds : NMC_FIELDS_NM_STATUS_COMMON;
315 316
	NmcOutputField *tmpl, *arr;
	size_t tmpl_len;
317

318 319 320 321
	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
		fields_str = fields_common;
	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
		fields_str = fields_all;
Jiří Klimeš's avatar
Jiří Klimeš committed
322
	else
323 324
		fields_str = nmc->required_fields;

325 326
	tmpl = nmc_fields_nm_status;
	tmpl_len = sizeof (nmc_fields_nm_status);
327
	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
328 329

	if (error) {
330
		g_string_printf (nmc->return_text, _("Error: only these fields are allowed: %s"), fields_all);
331
		g_error_free (error);
332
		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
333
		return FALSE;
334 335
	}

336 337 338
	nmc->get_client (nmc); /* create NMClient */

	nm_running = nm_client_get_manager_running (nmc->client);
339
	if (nm_running) {
340
		if (!nmc_versions_match (nmc))
341
			return FALSE;
342

343
		state = nm_client_get_state (nmc->client);
344
		startup = nm_client_get_startup (nmc->client);
Dan Winship's avatar
Dan Winship committed
345
		connectivity = nm_client_get_connectivity (nmc->client);
346
		net_enabled_str = nm_client_networking_get_enabled (nmc->client) ? _("enabled") : _("disabled");
347 348 349 350
		wireless_hw_enabled_str = nm_client_wireless_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled");
		wireless_enabled_str = nm_client_wireless_get_enabled (nmc->client) ? _("enabled") : _("disabled");
		wwan_hw_enabled_str = nm_client_wwan_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled");
		wwan_enabled_str = nm_client_wwan_get_enabled (nmc->client) ? _("enabled") : _("disabled");
351
#if WITH_WIMAX
352 353
		wimax_hw_enabled_str = nm_client_wimax_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled");
		wimax_enabled_str = nm_client_wimax_get_enabled (nmc->client) ? _("enabled") : _("disabled");
354
#endif
355
	} else {
356
#if WITH_WIMAX
357 358
		net_enabled_str = wireless_hw_enabled_str = wireless_enabled_str =
		wwan_hw_enabled_str = wwan_enabled_str = wimax_hw_enabled_str = wimax_enabled_str = _("unknown");
359 360 361 362
#else
		net_enabled_str = wireless_hw_enabled_str = wireless_enabled_str =
		wwan_hw_enabled_str = wwan_enabled_str = _("unknown");
#endif
363 364
	}

365
	nmc->print_fields.header_name = pretty_header_name ? (char *) pretty_header_name : _("NetworkManager status");
366 367 368 369 370 371 372
	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
	g_ptr_array_add (nmc->output_data, arr);

	arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
	set_val_strc (arr, 0, nm_running ? _("running") : _("not running"));
	set_val_strc (arr, 1, nm_running ? nm_client_get_version (nmc->client) : _("unknown"));
	set_val_strc (arr, 2, nm_state_to_string (state));
373
	set_val_strc (arr, 3, nm_running ? (startup ? _("starting") : _("started")) : _("unknown"));
374 375 376 377 378 379
	set_val_strc (arr, 4, nm_connectivity_to_string (connectivity));
	set_val_strc (arr, 5, net_enabled_str);
	set_val_strc (arr, 6, wireless_hw_enabled_str);
	set_val_strc (arr, 7, wireless_enabled_str);
	set_val_strc (arr, 8, wwan_hw_enabled_str);
	set_val_strc (arr, 9, wwan_enabled_str);
380
#if WITH_WIMAX
381 382
	set_val_strc (arr, 10, wimax_hw_enabled_str);
	set_val_strc (arr, 11, wimax_enabled_str);
383
#endif
384
	g_ptr_array_add (nmc->output_data, arr);
385

386
	print_data (nmc);  /* Print all data */
387

388
	return TRUE;
389 390
}

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK     "org.freedesktop.NetworkManager.enable-disable-network"
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI        "org.freedesktop.NetworkManager.enable-disable-wifi"
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN        "org.freedesktop.NetworkManager.enable-disable-wwan"
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX       "org.freedesktop.NetworkManager.enable-disable-wimax"
#define NM_AUTH_PERMISSION_SLEEP_WAKE                 "org.freedesktop.NetworkManager.sleep-wake"
#define NM_AUTH_PERMISSION_NETWORK_CONTROL            "org.freedesktop.NetworkManager.network-control"
#define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED       "org.freedesktop.NetworkManager.wifi.share.protected"
#define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN            "org.freedesktop.NetworkManager.wifi.share.open"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM     "org.freedesktop.NetworkManager.settings.modify.system"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN        "org.freedesktop.NetworkManager.settings.modify.own"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME   "org.freedesktop.NetworkManager.settings.modify.hostname"

static const char *
permission_to_string (NMClientPermission perm)
{
	switch (perm) {
	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK:
		return NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK;
	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI:
		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN:
		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
	case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX:
		return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
	case NM_CLIENT_PERMISSION_SLEEP_WAKE:
		return NM_AUTH_PERMISSION_SLEEP_WAKE;
	case NM_CLIENT_PERMISSION_NETWORK_CONTROL:
		return NM_AUTH_PERMISSION_NETWORK_CONTROL;
	case NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED:
		return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED;
	case NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN:
		return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN;
	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM:
		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN:
		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
	case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME:
		return NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
	default:
		return _("unknown");
	}
}

static const char *
permission_result_to_string (NMClientPermissionResult perm_result)
{
	
	switch (perm_result) {
	case NM_CLIENT_PERMISSION_RESULT_YES:
		return _("yes");
	case NM_CLIENT_PERMISSION_RESULT_NO:
		return _("no");
	case NM_CLIENT_PERMISSION_RESULT_AUTH:
		return _("auth");
	default:
		return _("unknown");
	}
}

450
static gboolean
451 452 453 454 455 456 457
show_nm_permissions (NmCli *nmc)
{
	NMClientPermission perm;
	GError *error = NULL;
	const char *fields_str;
	const char *fields_all =    NMC_FIELDS_NM_PERMISSIONS_ALL;
	const char *fields_common = NMC_FIELDS_NM_PERMISSIONS_COMMON;
458 459
	NmcOutputField *tmpl, *arr;
	size_t tmpl_len;
460 461 462 463 464 465 466 467

	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
		fields_str = fields_common;
	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
		fields_str = fields_all;
	else
		fields_str = nmc->required_fields;

468 469
	tmpl = nmc_fields_nm_permissions;
	tmpl_len = sizeof (nmc_fields_nm_permissions);
470
	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
471 472

	if (error) {
473
		g_string_printf (nmc->return_text, _("Error: 'general permissions': %s"), error->message);
474 475
		g_error_free (error);
		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
476
		return FALSE;
477 478
	}

479 480 481 482 483
	nmc->get_client (nmc); /* create NMClient */

	if (!nm_client_get_manager_running (nmc->client)) {
		g_string_printf (nmc->return_text, _("Error: NetworkManager is not running."));
		nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
484
		return FALSE;
485 486 487
	}

	nmc->print_fields.header_name = _("NetworkManager permissions");
488 489
	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
	g_ptr_array_add (nmc->output_data, arr);
490 491 492 493

	for (perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++) {
		NMClientPermissionResult perm_result = nm_client_get_permission_result (nmc->client, perm);

494 495 496 497
		arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
		set_val_strc (arr, 0, permission_to_string (perm));
		set_val_strc (arr, 1, permission_result_to_string (perm_result));
		g_ptr_array_add (nmc->output_data, arr);
498
	}
499
	print_data (nmc);  /* Print all data */
500

501
	return TRUE;
502 503
}

504 505 506 507 508 509 510 511 512
static gboolean
show_general_logging (NmCli *nmc)
{
	char *level = NULL;
	char *domains = NULL;
	GError *error = NULL;
	const char *fields_str;
	const char *fields_all =    NMC_FIELDS_NM_LOGGING_ALL;
	const char *fields_common = NMC_FIELDS_NM_LOGGING_COMMON;
513 514
	NmcOutputField *tmpl, *arr;
	size_t tmpl_len;
515 516 517 518 519 520 521 522

	if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
		fields_str = fields_common;
	else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
		fields_str = fields_all;
	else
		fields_str = nmc->required_fields;

523 524
	tmpl = nmc_fields_nm_logging;
	tmpl_len = sizeof (nmc_fields_nm_logging);
525
	nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
526

527
	if (error) {
528
		g_string_printf (nmc->return_text, _("Error: 'general logging': %s"), error->message);
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
		g_error_free (error);
		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
		return FALSE;
	}

	nmc->get_client (nmc); /* create NMClient */
	nm_client_get_logging (nmc->client, &level, &domains, &error);
	if (error) {
		g_string_printf (nmc->return_text, _("Error: %s."), error->message);
		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
		g_error_free (error);
		return FALSE;
	}

	nmc->print_fields.header_name = _("NetworkManager logging");
544 545 546 547 548 549 550
	arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
	g_ptr_array_add (nmc->output_data, arr);

	arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
	set_val_str (arr, 0, level);
	set_val_str (arr, 1, domains);
	g_ptr_array_add (nmc->output_data, arr);
551

552
	print_data (nmc);  /* Print all data */
553 554 555 556

	return TRUE;
}

557 558 559 560 561 562 563 564 565 566 567 568 569
static void
save_hostname_cb (NMRemoteSettings *settings, GError *error, gpointer user_data)
{
	NmCli *nmc = (NmCli *) user_data;

	if (error) {
		g_string_printf (nmc->return_text, _("Error: failed to set hostname: (%d) %s"),
		                 error->code, error->message);
		nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
	}
	quit ();
}

570 571 572 573 574 575 576 577 578 579 580 581 582 583
/*
 * Entry point function for general operations 'nmcli general'
 */
NMCResultCode
do_general (NmCli *nmc, int argc, char **argv)
{
	GError *error = NULL;

	if (argc == 0) {
		if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) {
			g_string_printf (nmc->return_text, _("Error: %s."), error->message);
			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
			goto finish;
		}
584
		show_nm_status (nmc, NULL, NULL);
585 586 587
	}

	if (argc > 0) {
588 589 590 591
		if (nmc_arg_is_help (*argv)) {
			usage_general ();
		}
		else if (matches (*argv, "status") == 0) {
592 593 594 595
			if (nmc_arg_is_help (*(argv+1))) {
				usage_general_status ();
				goto finish;
			}
596 597 598 599 600
			if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) {
				g_string_printf (nmc->return_text, _("Error: %s."), error->message);
				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
				goto finish;
			}
601
			show_nm_status (nmc, NULL, NULL);
602
		}
603 604 605
		else if (matches (*argv, "hostname") == 0) {
			NMRemoteSettings *rem_settings;

606 607 608 609 610
			if (nmc_arg_is_help (*(argv+1))) {
				usage_general_hostname ();
				goto finish;
			}

611
			/* get system settings */
612 613 614
			if (!(rem_settings = nm_remote_settings_new (NULL, &error))) {
				g_string_printf (nmc->return_text, _("Error: Could not get system settings: %s."), error->message);
				g_clear_error (&error);
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
				nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
				goto finish;
			}

			if (next_arg (&argc, &argv) != 0) {
				/* no arguments -> get hostname */
				char *hostname = NULL;

				g_object_get (rem_settings, NM_REMOTE_SETTINGS_HOSTNAME, &hostname, NULL);
				if (hostname)
					printf ("%s\n", hostname);
				g_free (hostname);
			} else {
				/* hostname provided -> set it */
				const char *hostname = *argv;

				if (next_arg (&argc, &argv) == 0)
					printf ("Warning: ignoring extra garbage after '%s' hostname\n", hostname);

				nmc->should_wait = TRUE;
				nm_remote_settings_save_hostname (rem_settings, hostname, save_hostname_cb, nmc);
			}
		}
638
		else if (matches (*argv, "permissions") == 0) {
639 640 641 642
			if (nmc_arg_is_help (*(argv+1))) {
				usage_general_permissions ();
				goto finish;
			}
643 644 645 646 647 648 649
			if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) {
				g_string_printf (nmc->return_text, _("Error: %s."), error->message);
				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
				goto finish;
			}
			show_nm_permissions (nmc);
		}
650
		else if (matches (*argv, "logging") == 0) {
651 652 653 654
			if (nmc_arg_is_help (*(argv+1))) {
				usage_general_logging ();
				goto finish;
			}
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
			if (next_arg (&argc, &argv) != 0) {
				/* no arguments -> get logging level and domains */
				if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) {
					g_string_printf (nmc->return_text, _("Error: %s."), error->message);
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					goto finish;
				}
				show_general_logging (nmc);
			} else {
				/* arguments provided -> set logging level and domains */
				const char *level = NULL;
				const char *domains = NULL;
				nmc_arg_t exp_args[] = { {"level",   TRUE, &level,   TRUE},
				                         {"domains", TRUE, &domains, TRUE},
				                         {NULL} };

				if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, &error)) {
					g_string_assign (nmc->return_text, error->message);
					nmc->return_value = error->code;
					goto finish;
				}

				nmc->get_client (nmc); /* create NMClient */
				nm_client_set_logging (nmc->client, level, domains, &error);
				if (error) {
680 681 682 683
					if (g_error_matches (error, DBUS_GERROR, DBUS_GERROR_ACCESS_DENIED))
						g_string_printf (nmc->return_text, _("Error: access denied to set logging; %s"), error->message);
					else
						g_string_printf (nmc->return_text, _("Error: %s"), error->message);
684 685 686 687 688
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					goto finish;
				}
			}
		}
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
		else {
			usage_general ();
			g_string_printf (nmc->return_text, _("Error: 'general' command '%s' is not valid."), *argv);
			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
		}
	}

finish:
	if (error)
		g_error_free (error);
	return nmc->return_value;
}

static gboolean
nmc_switch_show (NmCli *nmc, const char *switch_name, const char *header)
{
	g_return_val_if_fail (nmc != NULL, FALSE);
	g_return_val_if_fail (switch_name != NULL, FALSE);

	if (nmc->required_fields && strcasecmp (nmc->required_fields, switch_name) != 0) {
709
		g_string_printf (nmc->return_text, _("Error: '--fields' value '%s' is not valid here (allowed field: %s)"),
710 711 712 713 714 715 716
		                 nmc->required_fields, switch_name);
		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
		return FALSE;
	}
	if (nmc->print_output == NMC_PRINT_NORMAL)
		nmc->print_output = NMC_PRINT_TERSE;

717 718 719
	if (!nmc->required_fields)
		nmc->required_fields = g_strdup (switch_name);
	return show_nm_status (nmc, header, NULL);
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
}

static gboolean
nmc_switch_parse_on_off (NmCli *nmc, const char *arg1, const char *arg2, gboolean *res)
{
	g_return_val_if_fail (nmc != NULL, FALSE);
	g_return_val_if_fail (arg1 && arg2, FALSE);
	g_return_val_if_fail (res != NULL, FALSE);

	if (!strcmp (arg2, "on"))
		*res = TRUE;
	else if (!strcmp (arg2, "off"))
		*res = FALSE;
	else {
		g_string_printf (nmc->return_text, _("Error: invalid '%s' argument: '%s' (use on/off)."), arg1, arg2);
		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
		return FALSE;
	}

	return TRUE;
}

Dan Winship's avatar
Dan Winship committed
742 743 744
static gboolean
show_networking_connectivity (NmCli *nmc)
{
745
	return nmc_switch_show (nmc, NMC_FIELDS_NM_CONNECTIVITY, _("Connectivity"));
Dan Winship's avatar
Dan Winship committed
746 747
}

748
/*
749 750 751 752 753 754 755 756 757 758
 * Entry point function for 'nmcli networking'
 */
NMCResultCode
do_networking (NmCli *nmc, int argc, char **argv)
{
	gboolean enable_flag;

	if (argc == 0)
		nmc_switch_show (nmc, NMC_FIELDS_NM_NETWORKING, _("Networking"));
	else if (argc > 0) {
759
		if (nmc_arg_is_help (*argv)) {
760
			usage_networking ();
Dan Winship's avatar
Dan Winship committed
761
		} else if (matches (*argv, "connectivity") == 0) {
762 763 764 765
			if (nmc_arg_is_help (*(argv+1))) {
				usage_networking_connectivity ();
				goto finish;
			}
Dan Winship's avatar
Dan Winship committed
766 767 768 769 770 771 772 773 774 775
			if (next_arg (&argc, &argv) != 0) {
				/* no arguments -> get current state */
				show_networking_connectivity (nmc);
			} else if (matches (*argv, "check") == 0) {
				GError *error = NULL;

				nmc->get_client (nmc); /* create NMClient */
				nm_client_check_connectivity (nmc->client, NULL, &error);
				if (error) {
					g_string_printf (nmc->return_text, _("Error: %s."), error->message);
776 777
					nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
					g_clear_error (&error);
Dan Winship's avatar
Dan Winship committed
778 779 780 781 782 783 784
				} else
					show_networking_connectivity (nmc);
			} else {
				usage_networking ();
				g_string_printf (nmc->return_text, _("Error: 'networking connectivity' command '%s' is not valid."), *argv);
				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
			}
785
		} else if (nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag)) {
786 787 788 789 790 791 792
			if (nmc_arg_is_help (*(argv+1))) {
				if (enable_flag)
					usage_networking_on ();
				else
					usage_networking_off ();
				goto finish;
			}
793 794 795 796 797 798 799 800 801 802

			nmc->get_client (nmc); /* create NMClient */
			nm_client_networking_set_enabled (nmc->client, enable_flag);
		} else {
			usage_networking ();
			g_string_printf (nmc->return_text, _("Error: 'networking' command '%s' is not valid."), *argv);
			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
		}
	}

803
finish:
804 805 806 807 808 809
	quit ();
	return nmc->return_value;
}

/*
 * Entry point function for radio switch commands 'nmcli radio'
810 811
 */
NMCResultCode
812
do_radio (NmCli *nmc, int argc, char **argv)
813 814 815 816 817 818 819 820 821 822 823
{
	GError *error = NULL;
	gboolean enable_flag;

	if (argc == 0) {
		if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) {
			g_string_printf (nmc->return_text, _("Error: %s."), error->message);
			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
			g_error_free (error);
			goto finish;
		}
824
		show_nm_status (nmc, _("Radio switches"), NMC_FIELDS_NM_STATUS_RADIO);
825 826 827
	}

	if (argc > 0) {
828 829 830 831
		if (nmc_arg_is_help (*argv)) {
			usage_radio ();
		}
		else if (matches (*argv, "all") == 0) {
832 833 834 835
			if (nmc_arg_is_help (*(argv+1))) {
				usage_radio_all ();
				goto finish;
			}
836
			if (next_arg (&argc, &argv) != 0) {
837
				/* no argument, show all radio switches */
838 839 840 841 842 843
				if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) {
					g_string_printf (nmc->return_text, _("Error: %s."), error->message);
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					g_error_free (error);
					goto finish;
				}
844
				show_nm_status (nmc, _("Radio switches"), NMC_FIELDS_NM_STATUS_RADIO);
845 846 847 848 849 850 851 852 853 854 855
			} else {
				if (!nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag))
					goto finish;

				nmc->get_client (nmc); /* create NMClient */
				nm_client_wireless_set_enabled (nmc->client, enable_flag);
				nm_client_wimax_set_enabled (nmc->client, enable_flag);
				nm_client_wwan_set_enabled (nmc->client, enable_flag);
			}
		}
		else if (matches (*argv, "wifi") == 0) {
856 857 858 859
			if (nmc_arg_is_help (*(argv+1))) {
				usage_radio_wifi ();
				goto finish;
			}
860 861
			if (next_arg (&argc, &argv) != 0) {
				/* no argument, show current WiFi state */
862
				nmc_switch_show (nmc, NMC_FIELDS_NM_WIFI, _("Wi-Fi radio switch"));
863 864 865 866 867 868 869 870 871
			} else {
				if (!nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag))
					goto finish;
				
				nmc->get_client (nmc); /* create NMClient */
				nm_client_wireless_set_enabled (nmc->client, enable_flag);
			}
		}
		else if (matches (*argv, "wwan") == 0) {
872 873 874 875
			if (nmc_arg_is_help (*(argv+1))) {
				usage_radio_wwan ();
				goto finish;
			}
876
			if (next_arg (&argc, &argv) != 0) {
877 878
				/* no argument, show current WWAN (mobile broadband) state */
				nmc_switch_show (nmc, NMC_FIELDS_NM_WWAN, _("WWAN radio switch"));
879 880 881 882 883 884 885 886 887 888
			} else {
				if (!nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag))
					goto finish;

				nmc->get_client (nmc); /* create NMClient */
				nm_client_wwan_set_enabled (nmc->client, enable_flag);
			}
		}
#if WITH_WIMAX
		else if (matches (*argv, "wimax") == 0) {
889 890 891 892
			if (nmc_arg_is_help (*(argv+1))) {
				usage_radio_wimax ();
				goto finish;
			}
893 894
			if (next_arg (&argc, &argv) != 0) {
				/* no argument, show current WiMAX state */
895
				nmc_switch_show (nmc, NMC_FIELDS_NM_WIMAX, _("WiMAX radio switch"));
896 897 898 899 900 901 902 903 904 905
			} else {
				if (!nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag))
					goto finish;

				nmc->get_client (nmc); /* create NMClient */
				nm_client_wimax_set_enabled (nmc->client, enable_flag);
			}
		}
#endif
		else {
906 907
			usage_radio ();
			g_string_printf (nmc->return_text, _("Error: 'radio' command '%s' is not valid."), *argv);
908 909 910 911 912 913 914 915 916
			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
		}
	}

finish:
	quit ();
	return nmc->return_value;
}