1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* nm-platform.c - Handle runtime kernel networking configuration
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Copyright (C) 2013 Red Hat, Inc.
19 */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <arpa/inet.h>
25
26 #include "nm-platform.h"
27 #include "nm-linux-platform.h"
28 #include "nm-fake-platform.h"
29
30 #define error(...) fprintf (stderr, __VA_ARGS__)
31
32 typedef gboolean boolean_t;
33 typedef int decimal_t;
34 typedef const char *string_t;
35
36 #define print_boolean(value) printf ("%s\n", value ? "yes" : "no")
37 #define print_decimal(value) printf ("%d\n", value)
38 #define print_string(value) printf ("%s\n", value)
39
40 static gboolean
41 do_sysctl_set (char **argv)
42 {
43 return nm_platform_sysctl_set (argv[0], argv[1]);
44 }
45
46 static gboolean
47 do_sysctl_get (char **argv)
48 {
49 auto_g_free char *value = nm_platform_sysctl_get (argv[0]);
50
51 printf ("%s\n", value);
52
53 return !!value;
54 }
55
56 static int
57 parse_ifindex (const char *str)
58 {
59 char *endptr;
60 int ifindex = 0;
61
62 ifindex = strtol (str, &endptr, 10);
63
64 if (*endptr) {
65 ifindex = nm_platform_link_get_ifindex (str);
66 }
67
68 return ifindex;
69 }
70
71 static gboolean
72 do_link_get_all (char **argv)
73 {
74 GArray *links;
75 NMPlatformLink *device;
76 int i;
77
78 links = nm_platform_link_get_all ();
79 for (i = 0; i < links->len; i++) {
80 device = &g_array_index (links, NMPlatformLink, i);
81
82 printf ("%d: %s type %d\n", device->ifindex, device->name, device->type);
83 }
84 g_array_unref (links);
85
86 return TRUE;
87 }
88
89 static gboolean
90 do_dummy_add (char **argv)
91 {
92 return nm_platform_dummy_add (argv[0]);
93 }
94
95 static gboolean
96 do_bridge_add (char **argv)
97 {
98 return nm_platform_bridge_add (argv[0]);
99 }
100
101 static gboolean
102 do_bond_add (char **argv)
103 {
104 return nm_platform_bond_add (argv[0]);
105 }
106
107 static gboolean
108 do_team_add (char **argv)
109 {
110 return nm_platform_team_add (argv[0]);
111 }
112
113 static gboolean
114 do_vlan_add (char **argv)
115 {
116 const char *name = *argv++;
117 int parent = parse_ifindex (*argv++);
118 int vlanid = strtol (*argv++, NULL, 10);
119 guint32 vlan_flags = strtol (*argv++, NULL, 10);
120
121 return nm_platform_vlan_add (name, parent, vlanid, vlan_flags);
122 }
123
124 static gboolean
125 do_link_exists (char **argv)
126 {
127 gboolean value = nm_platform_link_exists (argv[0]);
128
129 print_boolean (value);
130
131 return TRUE;
132 }
133
134 #define LINK_CMD(cmdname) \
135 static gboolean \
136 do_link_##cmdname (char **argv) \
137 { \
138 int ifindex = parse_ifindex (argv[0]); \
139 return ifindex ? nm_platform_link_##cmdname (ifindex) : FALSE; \
140 }
141
142 #define LINK_CMD_GET_FULL(cmdname, type, cond) \
143 static gboolean \
144 do_link_##cmdname (char **argv) \
145 { \
146 int ifindex = parse_ifindex (argv[0]); \
147 if (ifindex) { \
148 type##_t value = nm_platform_link_##cmdname (ifindex); \
149 if (cond) { \
150 print_##type (value); \
151 return TRUE; \
152 } \
153 } \
154 return FALSE; \
155 }
156 #define LINK_CMD_GET(cmdname, type) LINK_CMD_GET_FULL (cmdname, type, TRUE);
157
158 LINK_CMD (delete)
159
160 /* do_link_delete_by_ifname:
161 *
162 * We don't need this as we allow ifname instead of ifindex anyway.
163 */
164
165 static gboolean
166 do_link_get_ifindex (char **argv)
167 {
168 int ifindex = nm_platform_link_get_ifindex (argv[0]);
169
170 if (ifindex)
171 printf ("%d\n", ifindex);
172
173 return !!ifindex;
174 }
175
176 LINK_CMD_GET_FULL (get_name, string, value)
177 LINK_CMD_GET_FULL (get_type, decimal, value > 0)
178 LINK_CMD_GET (is_software, boolean)
179 LINK_CMD_GET (supports_slaves, boolean)
180
181 LINK_CMD (set_up)
182 LINK_CMD (set_down)
183 LINK_CMD (set_arp)
184 LINK_CMD (set_noarp)
185 LINK_CMD_GET (is_up, boolean)
186 LINK_CMD_GET (is_connected, boolean)
187 LINK_CMD_GET (uses_arp, boolean)
188
189 static gboolean
190 do_link_set_address (char **argv)
191 {
192 int ifindex = parse_ifindex (*argv++);
193 char *hex = *argv++;
194 int hexlen = strlen (hex);
195 char address[hexlen/2];
196 char *endptr;
197 int i;
198
199 g_assert (!(hexlen % 2));
200
201 for (i = 0; i < sizeof (address); i++) {
202 char digit[3];
203
204 digit[0] = hex[2*i];
205 digit[1] = hex[2*i+1];
206 digit[2] = '\0';
207
208 address[i] = strtoul (digit, &endptr, 16);
209 g_assert (!*endptr);
210 }
211
212 return nm_platform_link_set_address (ifindex, address, sizeof (address));
213 }
214
215 static gboolean
216 do_link_get_address (char **argv)
217 {
218 int ifindex = parse_ifindex (*argv++);
219 const char *address;
220 size_t length;
221 int i;
222
223 address = nm_platform_link_get_address (ifindex, &length);
224
225 if (!address || length <= 0)
226 return FALSE;
227
228 for (i = 0; i < length; i++)
229 printf ("%02x", address[i]);
230 printf ("\n");
231
232 return TRUE;
233 }
234
235 static gboolean
236 do_link_set_mtu (char **argv)
237 {
238 int ifindex = parse_ifindex (*argv++);
239 int mtu = strtoul (*argv++, NULL, 10);
240
241 return nm_platform_link_set_mtu (ifindex, mtu);
242 }
243
244 LINK_CMD_GET (get_mtu, decimal);
245 LINK_CMD_GET (supports_carrier_detect, boolean)
246 LINK_CMD_GET (supports_vlans, boolean)
247
248 static gboolean
249 do_link_enslave (char **argv)
250 {
251 int master = parse_ifindex (*argv++);
252 int slave = parse_ifindex (*argv++);
253
254 return nm_platform_link_enslave (master, slave);
255 }
256
257 static gboolean
258 do_link_release (char **argv)
259 {
260 int master = parse_ifindex (*argv++);
261 int slave = parse_ifindex (*argv++);
262
263 return nm_platform_link_release (master, slave);
264 }
265
266 LINK_CMD_GET (get_master, decimal)
267
268 static gboolean
269 do_master_set_option (char **argv)
270 {
271 int ifindex = parse_ifindex (*argv++);
272 const char *option = *argv++;
273 const char *value = *argv++;
274
275 return nm_platform_master_set_option (ifindex, option, value);
276 }
277
278 static gboolean
279 do_master_get_option (char **argv)
280 {
281 int ifindex = parse_ifindex (*argv++);
282 const char *option = *argv++;
283 auto_g_free char *value = nm_platform_master_get_option (ifindex, option);
284
285 printf ("%s\n", value);
286
287 return !!value;
288 }
289
290 static gboolean
291 do_slave_set_option (char **argv)
292 {
293 int ifindex = parse_ifindex (*argv++);
294 const char *option = *argv++;
295 const char *value = *argv++;
296
297 return nm_platform_slave_set_option (ifindex, option, value);
298 }
299
300 static gboolean
301 do_slave_get_option (char **argv)
302 {
303 int ifindex = parse_ifindex (*argv++);
304 const char *option = *argv++;
305 auto_g_free char *value = nm_platform_slave_get_option (ifindex, option);
306
307 printf ("%s\n", value);
308
309 return !!value;
310 }
311
312 static gboolean
313 do_vlan_get_info (char **argv)
314 {
315 int ifindex = parse_ifindex (*argv++);
316 int parent;
317 int vlanid;
318
319 if (!nm_platform_vlan_get_info (ifindex, &parent, &vlanid))
320 return FALSE;
321
322 printf ("%d %d\n", parent, vlanid);
323
324 return TRUE;
325 }
326
327 static gboolean
328 do_vlan_set_ingress_map (char **argv)
329 {
330 int ifindex = parse_ifindex (*argv++);
331 int from = strtol (*argv++, NULL, 10);
332 int to = strtol (*argv++, NULL, 10);
333
334 return nm_platform_vlan_set_ingress_map (ifindex, from, to);
335 }
336
337 static gboolean
338 do_vlan_set_egress_map (char **argv)
339 {
340 int ifindex = parse_ifindex (*argv++);
341 int from = strtol (*argv++, NULL, 10);
342 int to = strtol (*argv++, NULL, 10);
343
344 return nm_platform_vlan_set_egress_map (ifindex, from, to);
345 }
346
347 static gboolean
348 do_veth_get_properties (char **argv)
349 {
350 int ifindex = parse_ifindex (*argv++);
351 NMPlatformVethProperties props;
352
353 if (!nm_platform_veth_get_properties (ifindex, &props))
354 return FALSE;
355
356 printf ("peer: %d\n", props.peer);
357
358 return TRUE;
359 }
360
361 static gboolean
362 do_tun_get_properties (char **argv)
363 {
364 int ifindex = parse_ifindex (*argv++);
365 NMPlatformTunProperties props;
366
367 if (!nm_platform_tun_get_properties (ifindex, &props))
368 return FALSE;
369
370 printf ("mode: %s\n", props.mode);
371 if (props.owner == -1)
372 printf ("owner: none\n");
373 else
374 printf ("owner: %lu\n", (gulong) props.owner);
375 if (props.group == -1)
376 printf ("group: none\n");
377 else
378 printf ("group: %lu\n", (gulong) props.group);
379 printf ("no-pi: ");
380 print_boolean (props.no_pi);
381 printf ("vnet-hdr: ");
382 print_boolean (props.vnet_hdr);
383 printf ("multi-queue: ");
384 print_boolean (props.multi_queue);
385
386 return TRUE;
387 }
388
389 static gboolean
390 do_macvlan_get_properties (char **argv)
391 {
392 int ifindex = parse_ifindex (*argv++);
393 NMPlatformMacvlanProperties props;
394
395 if (!nm_platform_macvlan_get_properties (ifindex, &props))
396 return FALSE;
397
398 printf ("parent: %d\n", props.parent_ifindex);
399 printf ("mode: %s\n", props.mode);
400 printf ("no-promisc: ");
401 print_boolean (props.no_promisc);
402 return TRUE;
403 }
404
405 static gboolean
406 do_gre_get_properties (char **argv)
407 {
408 int ifindex = parse_ifindex (*argv++);
409 NMPlatformGreProperties props;
410 char addrstr[INET_ADDRSTRLEN];
411
412 if (!nm_platform_gre_get_properties (ifindex, &props))
413 return FALSE;
414
415 printf ("parent-ifindex: %u\n", props.parent_ifindex);
416 printf ("input-flags: %u\n", props.input_flags);
417 printf ("output-flags: %u\n", props.input_flags);
418 printf ("input-key: %u\n", props.input_key);
419 printf ("output-key: %u\n", props.output_key);
420 if (props.local)
421 inet_ntop (AF_INET, &props.local, addrstr, sizeof (addrstr));
422 else
423 strcpy (addrstr, "-");
424 printf ("local: %s\n", addrstr);
425 if (props.remote)
426 inet_ntop (AF_INET, &props.remote, addrstr, sizeof (addrstr));
427 else
428 strcpy (addrstr, "-");
429 printf ("remote: %s\n", addrstr);
430 printf ("ttl: %u\n", props.ttl);
431 printf ("tos: %u\n", props.tos);
432 printf ("path-mtu-discovery: ");
433 print_boolean (props.path_mtu_discovery);
434
435 return TRUE;
436 }
437
438 static gboolean
439 do_ip4_address_get_all (char **argv)
440 {
441 int ifindex = parse_ifindex (argv[0]);
442 GArray *addresses;
443 NMPlatformIP4Address *address;
444 char addrstr[INET_ADDRSTRLEN];
445 int i;
446
447 if (ifindex) {
448 addresses = nm_platform_ip4_address_get_all (ifindex);
449 for (i = 0; i < addresses->len; i++) {
450 address = &g_array_index (addresses, NMPlatformIP4Address, i);
451 inet_ntop (AF_INET, &address->address, addrstr, sizeof (addrstr));
452 printf ("%s/%d\n", addrstr, address->plen);
453 }
454 g_array_unref (addresses);
455 }
456
457 return !!ifindex;
458 }
459
460 static gboolean
461 do_ip6_address_get_all (char **argv)
462 {
463 int ifindex = parse_ifindex (argv[0]);
464 GArray *addresses;
465 NMPlatformIP6Address *address;
466 char addrstr[INET6_ADDRSTRLEN];
467 int i;
468
469 if (ifindex) {
470 addresses = nm_platform_ip6_address_get_all (ifindex);
471 for (i = 0; i < addresses->len; i++) {
472 address = &g_array_index (addresses, NMPlatformIP6Address, i);
473 inet_ntop (AF_INET6, &address->address, addrstr, sizeof (addrstr));
474 printf ("%s/%d\n", addrstr, address->plen);
475 }
476 g_array_unref (addresses);
477 }
478
479 return !!ifindex;
480 }
481
482 static gboolean
483 parse_ip_address (int family, char *str, gpointer address, int *plen)
484 {
485 char *endptr;
486
487 if (plen) {
488 char *ptr = strchr (str, '/');
489 if (ptr) {
490 *ptr++ = '\0';
491 *plen = strtol (ptr, &endptr, 10);
492 if (*endptr)
493 ptr = NULL;
494 }
495 if (!ptr) {
496 error ("Bad format of IP address, expected address/plen.\n");
497 return FALSE;
498 }
499 }
500
501 if (inet_pton (family, str, address))
502 return TRUE;
503
504 error ("Bad format of IP address, expected address%s.\n", plen ? "/plen" : "");
505 return FALSE;
506 }
507
508 typedef in_addr_t ip4_t;
509 typedef struct in6_addr ip6_t;
510
511 #define parse_ip4_address(s, a, p) parse_ip_address (AF_INET, s, a, p)
512 #define parse_ip6_address(s, a, p) parse_ip_address (AF_INET6, s, a, p)
513
514 static gboolean
515 do_ip4_address_add (char **argv)
516 {
517 int ifindex = parse_ifindex (*argv++);
518 ip4_t address;
519 int plen;
520
521 if (ifindex && parse_ip4_address (*argv++, &address, &plen)) {
522 guint32 lifetime = strtol (*argv++, NULL, 10);
523 guint32 preferred = strtol (*argv++, NULL, 10);
524
525 gboolean value = nm_platform_ip4_address_add (ifindex, address, plen, lifetime, preferred);
526 return value;
527 } else
528 return FALSE;
529 }
530
531 static gboolean
532 do_ip6_address_add (char **argv)
533 {
534 int ifindex = parse_ifindex (*argv++);
535 ip6_t address;
536 int plen;
537
538 if (ifindex && parse_ip6_address (*argv++, &address, &plen)) {
539 guint32 lifetime = strtol (*argv++, NULL, 10);
540 guint32 preferred = strtol (*argv++, NULL, 10);
541
542 gboolean value = nm_platform_ip6_address_add (ifindex, address, plen, lifetime, preferred);
543 return value;
544 } else
545 return FALSE;
546 }
547
548 #define ADDR_CMD_FULL(v, cmdname, print) \
549 static gboolean \
550 do_##v##_address_##cmdname (char **argv) \
551 { \
552 int ifindex = parse_ifindex (*argv++); \
553 v##_t address; \
554 int plen; \
555 if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \
556 gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen); \
557 if (print) { \
558 print_boolean (value); \
559 return TRUE; \
560 } else \
561 return value; \
562 } else \
563 return FALSE; \
564 }
565 #define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE) ADDR_CMD_FULL (ip6, cmdname, FALSE)
566 #define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE)
567
568 ADDR_CMD (delete)
569 ADDR_CMD_PRINT (exists)
570
571 static gboolean
572 do_ip4_route_get_all (char **argv)
573 {
574 int ifindex = parse_ifindex (argv[0]);
575 GArray *routes;
576 NMPlatformIP4Route *route;
577 char networkstr[INET_ADDRSTRLEN], gatewaystr[INET_ADDRSTRLEN];
578 int i;
579
580 if (ifindex) {
581 routes = nm_platform_ip4_route_get_all (ifindex, TRUE);
582 for (i = 0; i < routes->len; i++) {
583 route = &g_array_index (routes, NMPlatformIP4Route, i);
584 inet_ntop (AF_INET, &route->network, networkstr, sizeof (networkstr));
585 inet_ntop (AF_INET, &route->gateway, gatewaystr, sizeof (gatewaystr));
586 printf ("%s/%d via %s metric %d\n",
587 networkstr, route->plen, gatewaystr, route->metric);
588 }
589 g_array_unref (routes);
590 }
591
592 return !!ifindex;
593 }
594
595 static gboolean
596 do_ip6_route_get_all (char **argv)
597 {
598 int ifindex = parse_ifindex (argv[0]);
599 GArray *routes;
600 NMPlatformIP6Route *route;
601 char networkstr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN];
602 int i;
603
604 if (ifindex) {
605 routes = nm_platform_ip6_route_get_all (ifindex, TRUE);
606 for (i = 0; i < routes->len; i++) {
607 route = &g_array_index (routes, NMPlatformIP6Route, i);
608 inet_ntop (AF_INET6, &route->network, networkstr, sizeof (networkstr));
609 inet_ntop (AF_INET6, &route->gateway, gatewaystr, sizeof (gatewaystr));
610 printf ("%s/%d via %s metric %d\n",
611 networkstr, route->plen, gatewaystr, route->metric);
612 }
613 g_array_unref (routes);
614 }
615
616 return !!ifindex;
617 }
618
619 static gboolean
620 do_ip4_route_add (char **argv)
621 {
622 int ifindex = parse_ifindex (*argv++);
623 in_addr_t network, gateway;
624 int plen, metric, mss;
625
626 parse_ip4_address (*argv++, &network, &plen);
627 parse_ip4_address (*argv++, &gateway, NULL);
628 metric = strtol (*argv++, NULL, 10);
629 mss = strtol (*argv++, NULL, 10);
630
631 return nm_platform_ip4_route_add (ifindex, network, plen, gateway, metric, mss);
632 }
633
634 static gboolean
635 do_ip6_route_add (char **argv)
636 {
637 int ifindex = parse_ifindex (*argv++);
638 struct in6_addr network, gateway;
639 int plen, metric, mss;
640
641 parse_ip6_address (*argv++, &network, &plen);
642 parse_ip6_address (*argv++, &gateway, NULL);
643 metric = strtol (*argv++, NULL, 10);
644 mss = strtol (*argv++, NULL, 10);
645 return nm_platform_ip6_route_add (ifindex, network, plen, gateway, metric, mss);
646 }
647
648 static gboolean
649 do_ip4_route_delete (char **argv)
650 {
651 int ifindex = parse_ifindex (*argv++);
652 in_addr_t network;
653 int plen, metric;
654
655 parse_ip4_address (*argv++, &network, &plen);
656 metric = strtol (*argv++, NULL, 10);
657
658 return nm_platform_ip4_route_delete (ifindex, network, plen, metric);
659 }
660
661 static gboolean
662 do_ip6_route_delete (char **argv)
663 {
664 int ifindex = parse_ifindex (*argv++);
665 struct in6_addr network;
666 int plen, metric;
667
668 parse_ip6_address (*argv++, &network, &plen);
669 metric = strtol (*argv++, NULL, 10);
670
671 return nm_platform_ip6_route_delete (ifindex, network, plen, metric);
672 }
673
674 static gboolean
675 do_ip4_route_exists (char **argv)
676 {
677 int ifindex = parse_ifindex (*argv++);
678 in_addr_t network;
679 int plen, metric;
680
681 parse_ip4_address (*argv++, &network, &plen);
682 metric = strtol (*argv++, NULL, 10);
683
684 print_boolean (nm_platform_ip4_route_exists (ifindex, network, plen, metric));
685 return TRUE;
686 }
687
688 static gboolean
689 do_ip6_route_exists (char **argv)
690 {
691 int ifindex = parse_ifindex (*argv++);
692 struct in6_addr network;
693 int plen, metric;
694
695 parse_ip6_address (*argv++, &network, &plen);
696 metric = strtol (*argv++, NULL, 10);
697
698 print_boolean (nm_platform_ip6_route_exists (ifindex, network, plen, metric));
699 return TRUE;
700 }
701
702 typedef struct {
703 const char *name;
704 const char *help;
705 int (*handler) (char **argv);
706 int argc;
707 const char *arghelp;
708 } command_t;
709
710 static const command_t commands[] = {
711 { "sysctl-set", "get /proc/sys or /sys value", do_sysctl_set, 2, "<path> <value>" },
712 { "sysctl-get", "get /proc/sys or /sys value", do_sysctl_get, 1, "<value>" },
713 { "link-get-all", "print all links", do_link_get_all, 0, "" },
714 { "dummy-add", "add dummy interface", do_dummy_add, 1, "<ifname>" },
715 { "bridge-add", "add bridge interface", do_bridge_add, 1, "<ifname>" },
716 { "bond-add", "add bond interface", do_bond_add, 1, "<ifname>" },
717 { "team-add", "add team interface", do_team_add, 1, "<ifname>" },
718 { "vlan-add", "add vlan interface", do_vlan_add, 4, "<ifname> <parent> <vlanid> <vlanflags>" },
719 { "link-exists", "check ifname for existance", do_link_exists, 1, "<ifname>" },
720 { "link-delete", "delete interface", do_link_delete, 1, "<ifname/ifindex>" },
721 { "link-get-ifindex>", "get interface index", do_link_get_ifindex, 1, "<ifname>" },
722 { "link-get-name", "get interface name", do_link_get_name, 1, "<ifindex>" },
723 { "link-get-type", "get interface type", do_link_get_type, 1, "<ifname/ifindex>" },
724 { "link-is-software", "check if interface is a software one", do_link_is_software, 1, "<ifname/ifindex>" },
725 { "link-supports-slaves", "check if interface supports slaves", do_link_supports_slaves, 1, "<ifname/ifindex>" },
726 { "link-set-up", "set interface up", do_link_set_up, 1, "<ifname/ifindex>" },
727 { "link-set-down", "set interface down", do_link_set_down, 1, "<ifname/ifindex>" },
728 { "link-set-arp", "activate interface arp", do_link_set_arp, 1, "<ifname/ifindex>" },
729 { "link-set-noarp", "deactivate interface arp", do_link_set_noarp, 1, "<ifname/ifindex>" },
730 { "link-is-up", "check if interface is up", do_link_is_up, 1, "<ifname/ifindex>" },
731 { "link-is-connected", "check interface carrier", do_link_is_connected, 1, "<ifname/ifindex>" },
732 { "link-uses-arp", "check whether interface uses arp", do_link_uses_arp, 1, "<ifname/ifindex>" },
733 { "link-get-address", "print link address", do_link_get_address, 1, "<ifname/ifindex>" },
734 { "link-set-address", "set link address", do_link_set_address, 2, "<ifname/ifindex> <hex>" },
735 { "link-get-mtu", "print link mtu", do_link_get_mtu, 1, "<ifname/ifindex>" },
736 { "link-set-mtu", "set link mtu", do_link_set_mtu, 2, "<ifname/ifindex> <mtu>" },
737 { "link-supports-carrier-detect", "check whether interface supports carrier detect",
738 do_link_supports_carrier_detect, 1, "<ifname/ifindex>" },
739 { "link-supports-vlans", "check whether interface supports VLANs",
740 do_link_supports_vlans, 1, "<ifname/ifindex>" },
741 { "link-enslave", "enslave slave interface with master", do_link_enslave, 2, "<master> <slave>" },
742 { "link-release", "release save interface from master", do_link_release, 2, "<master> <slave>" },
743 { "link-get-master", "print master interface of a slave", do_link_get_master, 1, "<ifname/ifindex>" },
744 { "link-master-set-option", "set master option", do_master_set_option, 3,
745 "<ifname/ifindex> <option> <value>" },
746 { "link-master-get-option", "get master option", do_master_get_option, 2,
747 "<ifname/ifindex> <option>" },
748 { "link-slave-set-option", "set slave option", do_slave_set_option, 3,
749 "<ifname/ifindex> <option>" },
750 { "link-slave-get-option", "get slave option", do_slave_get_option, 2,
751 "<ifname/ifindex> <option>" },
752 { "vlan-get-info", "get vlan info", do_vlan_get_info, 1, "<ifname/ifindex>" },
753 { "vlan-set-ingress-map", "set vlan ingress map", do_vlan_set_ingress_map, 3,
754 "<ifname/ifindex> <from> <to>" },
755 { "vlan-set-egress-map", "set vlan egress map", do_vlan_set_egress_map, 3,
756 "<ifname/ifindex> <from> <to>" },
757 { "veth-get-properties", "get veth properties", do_veth_get_properties, 1,
758 "<ifname/ifindex>" },
759 { "tun-get-properties", "get tun/tap properties", do_tun_get_properties, 1,
760 "<ifname/ifindex>" },
761 { "macvlan-get-properties", "get macvlan properties", do_macvlan_get_properties, 1,
762 "<ifname/ifindex>" },
763 { "gre-get-properties", "get gre properties", do_gre_get_properties, 1,
764 "<ifname/ifindex>" },
765 { "ip4-address-get-all", "print all IPv4 addresses", do_ip4_address_get_all, 1, "<ifname/ifindex>" },
766 { "ip6-address-get-all", "print all IPv6 addresses", do_ip6_address_get_all, 1, "<ifname/ifindex>" },
767 { "ip4-address-add", "add IPv4 address", do_ip4_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> <>" },
768 { "ip6-address-add", "add IPv6 address", do_ip6_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> <>" },
769 { "ip4-address-delete", "delete IPv4 address", do_ip4_address_delete, 2,
770 "<ifname/ifindex> <address>/<plen>" },
771 { "ip6-address-delete", "delete IPv6 address", do_ip6_address_delete, 2,
772 "<ifname/ifindex> <address>/<plen>" },
773 { "ip4-address-exists", "check for existence of IPv4 address", do_ip4_address_exists, 2,
774 "<ifname/ifindex> <address>/<plen>" },
775 { "ip6-address-exists", "check for existence of IPv6 address", do_ip6_address_exists, 2,
776 "<ifname/ifindex> <address>/<plen>" },
777 { "ip4-route-get-all", "print all IPv4 routes", do_ip4_route_get_all, 1, "<ifname/ifindex>" },
778 { "ip6-route-get-all", "print all IPv6 routes", do_ip6_route_get_all, 1, "<ifname/ifindex>" },
779 { "ip4-route-add", "add IPv4 route", do_ip4_route_add, 5,
780 "<ifname/ifindex> <network>/<plen> <gateway> <metric> <mss>" },
781 { "ip6-route-add", "add IPv6 route", do_ip6_route_add, 5,
782 "<ifname/ifindex> <network>/<plen> <gateway> <metric> <mss>" },
783 { "ip4-route-delete", "delete IPv4 route", do_ip4_route_delete, 3,
784 "<ifname/ifindex> <network>/<plen> <metric>" },
785 { "ip6-route-delete", "delete IPv6 route", do_ip6_route_delete, 3,
786 "<ifname/ifindex> <network>/<plen> <metric>" },
787 { "ip4-route-exists", "check for existence of IPv4 route", do_ip4_route_exists, 3,
788 "<ifname/ifindex> <network>/<plen> <metric>" },
789 { "ip6-route-exists", "check for existence of IPv6 route", do_ip6_route_exists, 3,
790 "<ifname/ifindex> <network>/<plen> <metric>" },
791 { NULL, NULL, NULL, 0, NULL },
792 };
793
794 int
795 main (int argc, char **argv)
796 {
797 const char *arg0 = *argv++;
798 const command_t *command = NULL;
799 gboolean status = TRUE;
800 int error;
801
802 g_type_init ();
803
804 if (*argv && !g_strcmp0 (argv[1], "--fake")) {
805 nm_fake_platform_setup ();
806 } else
807 nm_linux_platform_setup ();
808
809 if (*argv)
810 for (command = commands; command->name; command++)
811 if (g_str_has_prefix (command->name, *argv))
812 break;
813
814 if (command && command->name) {
815 argv++;
816 if (g_strv_length (argv) == command->argc)
817 status = command->handler (argv);
818 else {
819 error ("Wrong number of arguments to '%s' (expected %d).\n\nUsage: %s %s %s\n-- %s\n",
820 command->name, command->argc,
821 arg0, command->name, command->arghelp, command->help);
822 return EXIT_FAILURE;
823 }
824 } else {
825 error ("Usage: %s COMMAND\n\n", arg0);
826 error ("COMMAND\n");
827 for (command = commands; command->name; command++)
828 error (" %s %s\n -- %s\n", command->name, command->arghelp, command->help);
829 error ("\n");
830 }
831
832 error = nm_platform_get_error ();
833 if (error) {
834 const char *msg = nm_platform_get_error_msg ();
835
836 error ("nm-platform: %s\n", msg);
837 }
838
839 return !!error;
840 }
841