network-manager.c 17 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 - 2011 Red Hat, Inc.
18 19 20 21 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 <nm-client.h>
#include <nm-setting-connection.h>

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


33 34 35 36
/* Available fields for 'nm status' */
static NmcOutputField nmc_fields_nm_status[] = {
	{"RUNNING",        N_("RUNNING"),         15, NULL, 0},  /* 0 */
	{"STATE",          N_("STATE"),           15, NULL, 0},  /* 1 */
37 38 39 40 41
	{"NET-ENABLED",    N_("NET-ENABLED"),     13, NULL, 0},  /* 2 */
	{"WIFI-HARDWARE",  N_("WIFI-HARDWARE"),   15, NULL, 0},  /* 3 */
	{"WIFI",           N_("WIFI"),            10, NULL, 0},  /* 4 */
	{"WWAN-HARDWARE",  N_("WWAN-HARDWARE"),   15, NULL, 0},  /* 5 */
	{"WWAN",           N_("WWAN"),            10, NULL, 0},  /* 6 */
42 43 44
	{"WIMAX-HARDWARE", N_("WIMAX-HARDWARE"),  15, NULL, 0},  /* 7 */
	{"WIMAX",          N_("WIMAX"),           10, NULL, 0},  /* 8 */
	{NULL,             NULL,                  0, NULL, 0}
45
};
46
#define NMC_FIELDS_NM_STATUS_ALL     "RUNNING,STATE,NET-ENABLED,WIFI-HARDWARE,WIFI,WWAN-HARDWARE,WWAN,WIMAX-HARDWARE,WIMAX"
47
#define NMC_FIELDS_NM_STATUS_COMMON  "RUNNING,STATE,WIFI-HARDWARE,WIFI,WWAN-HARDWARE,WWAN"
48
#define NMC_FIELDS_NM_NET_ENABLED    "NET-ENABLED"
49 50
#define NMC_FIELDS_NM_WIFI           "WIFI"
#define NMC_FIELDS_NM_WWAN           "WWAN"
51
#define NMC_FIELDS_NM_WIMAX          "WIMAX"
52 53


54 55 56 57 58 59 60 61 62 63 64 65 66 67
extern GMainLoop *loop;

/* static function prototypes */
static void usage (void);
static void quit (void);
static const char *nm_state_to_string (NMState state);
static NMCResultCode show_nm_status (NmCli *nmc);


static void
usage (void)
{
	fprintf (stderr,
	 	 _("Usage: nmcli nm { COMMAND | help }\n\n"
68
		 "  COMMAND := { status | enable | sleep | wifi | wwan | wimax }\n\n"
69
		 "  status\n"
70 71
		 "  enable [true|false]\n"
		 "  sleep [true|false]\n"
72
		 "  wifi [on|off]\n"
73 74
		 "  wwan [on|off]\n"
		 "  wimax [on|off]\n\n"));
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
}

/* 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");
	case NM_STATE_CONNECTED:
		return _("connected");
	case NM_STATE_DISCONNECTED:
		return _("disconnected");
	case NM_STATE_UNKNOWN:
	default:
		return _("unknown");
	}
}

static NMCResultCode
show_nm_status (NmCli *nmc)
{
	gboolean nm_running;
106 107
	NMState state = NM_STATE_UNKNOWN;
	const char *net_enabled_str;
108 109
	const char *wireless_hw_enabled_str, *wireless_enabled_str;
	const char *wwan_hw_enabled_str, *wwan_enabled_str;
110
	const char *wimax_hw_enabled_str, *wimax_enabled_str;
111 112 113 114 115 116 117
	GError *error = NULL;
	const char *fields_str;
	const char *fields_all =    NMC_FIELDS_NM_STATUS_ALL;
	const char *fields_common = NMC_FIELDS_NM_STATUS_COMMON;
	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
118

119 120 121 122 123 124 125 126 127 128 129
	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;

	nmc->allowed_fields = nmc_fields_nm_status;
	nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &error);

	if (error) {
130 131 132 133
		if (error->code == 0)
			g_string_printf (nmc->return_text, _("Error: 'nm status': %s"), error->message);
		else
			g_string_printf (nmc->return_text, _("Error: 'nm status': %s; allowed fields: %s"), error->message, NMC_FIELDS_NM_STATUS_ALL);
134
		g_error_free (error);
135
		nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
136 137 138
		return nmc->return_value;
	}

Jiří Klimeš's avatar
Jiří Klimeš committed
139
	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES;
140 141 142
	nmc->print_fields.header_name = _("NetworkManager status");
	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */

143
	nm_running = nmc_is_nm_running (nmc, NULL);
144
	if (nm_running) {
145 146 147
		nmc->get_client (nmc); /* create NMClient */
		state = nm_client_get_state (nmc->client);
		net_enabled_str = nm_client_networking_get_enabled (nmc->client) ? _("enabled") : _("disabled");
148 149 150 151
		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");
152 153
		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");
154
	} else {
155 156
		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");
157 158
	}

159 160
	nmc->allowed_fields[0].value = nm_running ? _("running") : _("not running");
	nmc->allowed_fields[1].value = nm_state_to_string (state);
161
	nmc->allowed_fields[2].value = net_enabled_str;
162 163 164 165
	nmc->allowed_fields[3].value = wireless_hw_enabled_str;
	nmc->allowed_fields[4].value = wireless_enabled_str;
	nmc->allowed_fields[5].value = wwan_hw_enabled_str;
	nmc->allowed_fields[6].value = wwan_enabled_str;
166 167
	nmc->allowed_fields[7].value = wimax_hw_enabled_str;
	nmc->allowed_fields[8].value = wimax_enabled_str;
168

Jiří Klimeš's avatar
Jiří Klimeš committed
169
	nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag;
170
	print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
171 172 173 174

	return NMC_RESULT_SUCCESS;
}

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
/* libnm-glib doesn't provide API fro Sleep method - implement D-Bus call ourselves */
static void networking_set_sleep (NmCli *nmc, gboolean in_sleep)
{
	DBusGConnection *connection = NULL;
	DBusGProxy *proxy = NULL;
	GError *err = NULL;

	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
	if (!connection) {
		g_string_printf (nmc->return_text, _("Error: Couldn't connect to system bus: %s"), err->message);
		nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
        	g_error_free (err);
	        goto gone;
	}

	proxy = dbus_g_proxy_new_for_name (connection,
	                                   "org.freedesktop.NetworkManager",
	                                   "/org/freedesktop/NetworkManager",
	                                   "org.freedesktop.NetworkManager");
	if (!proxy) {
		g_string_printf (nmc->return_text, _("Error: Couldn't create D-Bus object proxy."));
		nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
		goto gone;
        }
 
	if (!dbus_g_proxy_call (proxy, "Sleep", &err, G_TYPE_BOOLEAN, in_sleep, G_TYPE_INVALID, G_TYPE_INVALID)) {
		g_string_printf (nmc->return_text, _("Error in sleep: %s"), err->message);
		nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
		g_error_free (err);
	}

gone:
	if (connection) dbus_g_connection_unref (connection);
	if (proxy) g_object_unref (proxy);
}
210 211 212 213 214

/* entry point function for global network manager related commands 'nmcli nm' */
NMCResultCode
do_network_manager (NmCli *nmc, int argc, char **argv)
{
215
	GError *error = NULL;
216 217
	gboolean sleep_flag;
	gboolean enable_net;
218 219
	gboolean enable_wifi;
	gboolean enable_wwan;
220
	gboolean enable_wimax;
221 222 223
	guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
	guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
	guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
224 225

	if (argc == 0) {
226
		if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error))
227
			goto opt_error;
228 229 230 231 232
		nmc->return_value = show_nm_status (nmc);
	}

	if (argc > 0) {
		if (matches (*argv, "status") == 0) {
233
			if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error))
234
				goto opt_error;
235 236
			nmc->return_value = show_nm_status (nmc);
		}
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
		else if (matches (*argv, "enable") == 0) {
			if (next_arg (&argc, &argv) != 0) {
				/* no argument, show current state of networking */
				if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error))
					goto opt_error;
				if (nmc->required_fields && strcasecmp (nmc->required_fields, "NET-ENABLED")) {
					g_string_printf (nmc->return_text, _("Error: '--fields' value '%s' is not valid here; allowed fields: %s"),
					                 nmc->required_fields, NMC_FIELDS_NM_NET_ENABLED);
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					goto end;
				}
				nmc->allowed_fields = nmc_fields_nm_status;
				nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_NM_NET_ENABLED, nmc->allowed_fields, NULL);
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES;
				nmc->print_fields.header_name = _("Networking enabled");
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
253

254
				if (nmc_is_nm_running (nmc, NULL)) {
255 256 257 258
					nmc->get_client (nmc); /* create NMClient */
					nmc->allowed_fields[2].value = nm_client_networking_get_enabled (nmc->client) ? _("enabled") : _("disabled");
				} else
					nmc->allowed_fields[2].value = _("unknown");
259
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag;
260
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
261 262 263 264 265 266 267 268 269 270
			} else {
				if (!strcmp (*argv, "true"))
					enable_net = TRUE;
				else if (!strcmp (*argv, "false"))
					enable_net = FALSE;
				else {
					g_string_printf (nmc->return_text, _("Error: invalid 'enable' parameter: '%s'; use 'true' or 'false'."), *argv);
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					goto end;
				}
271
				nmc->get_client (nmc); /* create NMClient */
272 273
				nm_client_networking_set_enabled (nmc->client, enable_net);
			}
274
		}
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
		else if (matches (*argv, "sleep") == 0) {
			if (next_arg (&argc, &argv) != 0) {
				g_string_printf (nmc->return_text, _("Error: Sleeping status is not exported by NetworkManager."));
				nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
			} else {
				if (!strcmp (*argv, "true"))
					sleep_flag = TRUE;
				else if (!strcmp (*argv, "false"))
					sleep_flag = FALSE;
				else {
					g_string_printf (nmc->return_text, _("Error: invalid 'sleep' parameter: '%s'; use 'true' or 'false'."), *argv);
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					goto end;
				}
				networking_set_sleep (nmc, sleep_flag);
			}
291 292 293
		}
		else if (matches (*argv, "wifi") == 0) {
			if (next_arg (&argc, &argv) != 0) {
294
				/* no argument, show current WiFi state */
295
				if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error))
296
					goto opt_error;
297
				if (nmc->required_fields && strcasecmp (nmc->required_fields, "WIFI")) {
298
					g_string_printf (nmc->return_text, _("Error: '--fields' value '%s' is not valid here; allowed fields: %s"),
299
					                 nmc->required_fields, NMC_FIELDS_NM_WIFI);
300
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
301 302 303 304
					goto end;
				}
				nmc->allowed_fields = nmc_fields_nm_status;
				nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_NM_WIFI, nmc->allowed_fields, NULL);
Jiří Klimeš's avatar
Jiří Klimeš committed
305
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES;
306 307
				nmc->print_fields.header_name = _("WiFi enabled");
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
308

309
				if (nmc_is_nm_running (nmc, NULL)) {
310 311 312 313
					nmc->get_client (nmc); /* create NMClient */
					nmc->allowed_fields[4].value = nm_client_wireless_get_enabled (nmc->client) ? _("enabled") : _("disabled");
				} else
					nmc->allowed_fields[4].value = _("unknown");
Jiří Klimeš's avatar
Jiří Klimeš committed
314
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag;
315
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
316 317 318 319 320 321 322
			} else {
				if (!strcmp (*argv, "on"))
					enable_wifi = TRUE;
				else if (!strcmp (*argv, "off"))
					enable_wifi = FALSE;
				else {
					g_string_printf (nmc->return_text, _("Error: invalid 'wifi' parameter: '%s'."), *argv);
323
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
324 325
					goto end;
				}
326
				nmc->get_client (nmc); /* create NMClient */
327 328 329 330 331
				nm_client_wireless_set_enabled (nmc->client, enable_wifi);
			}
		}
		else if (matches (*argv, "wwan") == 0) {
			if (next_arg (&argc, &argv) != 0) {
332
				if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error))
333
					goto opt_error;
334 335
				/* no argument, show current WWAN state */
				if (nmc->required_fields && strcasecmp (nmc->required_fields, "WWAN")) {
336
					g_string_printf (nmc->return_text, _("Error: '--fields' value '%s' is not valid here; allowed fields: %s"),
337
					                 nmc->required_fields, NMC_FIELDS_NM_WWAN);
338
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
339 340 341 342
					goto end;
				}
				nmc->allowed_fields = nmc_fields_nm_status;
				nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_NM_WWAN, nmc->allowed_fields, NULL);
Jiří Klimeš's avatar
Jiří Klimeš committed
343
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES;
344 345
				nmc->print_fields.header_name = _("WWAN enabled");
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
346

347
				if (nmc_is_nm_running (nmc, NULL)) {
348 349 350 351
					nmc->get_client (nmc); /* create NMClient */
					nmc->allowed_fields[6].value = nm_client_wwan_get_enabled (nmc->client) ? _("enabled") : _("disabled");
				} else
					nmc->allowed_fields[6].value = _("unknown");
Jiří Klimeš's avatar
Jiří Klimeš committed
352
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag;
353
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
354 355 356 357 358 359 360
			} else {
				if (!strcmp (*argv, "on"))
					enable_wwan = TRUE;
				else if (!strcmp (*argv, "off"))
					enable_wwan = FALSE;
				else {
					g_string_printf (nmc->return_text, _("Error: invalid 'wwan' parameter: '%s'."), *argv);
361
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
362 363
					goto end;
				}
364
				nmc->get_client (nmc); /* create NMClient */
365 366 367
				nm_client_wwan_set_enabled (nmc->client, enable_wwan);
			}
		}
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
		else if (matches (*argv, "wimax") == 0) {
			if (next_arg (&argc, &argv) != 0) {
				if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error))
					goto opt_error;
				/* no argument, show current WiMAX state */
				if (nmc->required_fields && strcasecmp (nmc->required_fields, "WIMAX")) {
					g_string_printf (nmc->return_text, _("Error: '--fields' value '%s' is not valid here; allowed fields: %s"),
					                 nmc->required_fields, NMC_FIELDS_NM_WIMAX);
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					goto end;
				}
				nmc->allowed_fields = nmc_fields_nm_status;
				nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_NM_WIMAX, nmc->allowed_fields, NULL);
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES;
				nmc->print_fields.header_name = _("WiMAX enabled");
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
384

385
				if (nmc_is_nm_running (nmc, NULL)) {
386 387 388 389
					nmc->get_client (nmc); /* create NMClient */
					nmc->allowed_fields[8].value = nm_client_wimax_get_enabled (nmc->client) ? _("enabled") : _("disabled");
				} else
					nmc->allowed_fields[8].value = _("unknown");
390
				nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag;
391
				print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */
392 393 394 395 396 397 398 399 400 401
			} else {
				if (!strcmp (*argv, "on"))
					enable_wimax = TRUE;
				else if (!strcmp (*argv, "off"))
					enable_wimax = FALSE;
				else {
					g_string_printf (nmc->return_text, _("Error: invalid 'wimax' parameter: '%s'."), *argv);
					nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
					goto end;
				}
402
				nmc->get_client (nmc); /* create NMClient */
403 404 405
				nm_client_wimax_set_enabled (nmc->client, enable_wimax);
			}
		}
406 407 408 409 410
		else if (strcmp (*argv, "help") == 0) {
			usage ();
		}
		else {
			g_string_printf (nmc->return_text, _("Error: 'nm' command '%s' is not valid."), *argv);
411
			nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
412 413 414 415 416 417
		}
	}

end:
	quit ();
	return nmc->return_value;
418

419
opt_error:
420 421
	quit ();
	g_string_printf (nmc->return_text, _("Error: %s."), error->message);
422
	nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
423 424
	g_error_free (error);
	return nmc->return_value;
425
}