16e91bba0SGirish Moodalbail /*
26e91bba0SGirish Moodalbail * CDDL HEADER START
36e91bba0SGirish Moodalbail *
46e91bba0SGirish Moodalbail * The contents of this file are subject to the terms of the
56e91bba0SGirish Moodalbail * Common Development and Distribution License (the "License").
66e91bba0SGirish Moodalbail * You may not use this file except in compliance with the License.
76e91bba0SGirish Moodalbail *
86e91bba0SGirish Moodalbail * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96e91bba0SGirish Moodalbail * or http://www.opensolaris.org/os/licensing.
106e91bba0SGirish Moodalbail * See the License for the specific language governing permissions
116e91bba0SGirish Moodalbail * and limitations under the License.
126e91bba0SGirish Moodalbail *
136e91bba0SGirish Moodalbail * When distributing Covered Code, include this CDDL HEADER in each
146e91bba0SGirish Moodalbail * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156e91bba0SGirish Moodalbail * If applicable, add the following below this CDDL HEADER, with the
166e91bba0SGirish Moodalbail * fields enclosed by brackets "[]" replaced with your own identifying
176e91bba0SGirish Moodalbail * information: Portions Copyright [yyyy] [name of copyright owner]
186e91bba0SGirish Moodalbail *
196e91bba0SGirish Moodalbail * CDDL HEADER END
206e91bba0SGirish Moodalbail */
218c8556f9SYuri Pankov
226e91bba0SGirish Moodalbail /*
238b88711aSGirish Moodalbail * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24cbf54fedSJohn Levon * Copyright (c) 2018, Joyent, Inc.
25d7c57852SGary Mills * Copyright 2017 Gary Mills
26b31320a7SChris Fraire * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
27a73be61aSHans Rosenfeld * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
28f3f00a64SAndy Fiddaman * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
296e91bba0SGirish Moodalbail */
308c8556f9SYuri Pankov
316e91bba0SGirish Moodalbail #include <arpa/inet.h>
326e91bba0SGirish Moodalbail #include <errno.h>
336e91bba0SGirish Moodalbail #include <getopt.h>
346e91bba0SGirish Moodalbail #include <inet/ip.h>
356e91bba0SGirish Moodalbail #include <inet/iptun.h>
366e91bba0SGirish Moodalbail #include <inet/tunables.h>
376e91bba0SGirish Moodalbail #include <libdladm.h>
386e91bba0SGirish Moodalbail #include <libdliptun.h>
396e91bba0SGirish Moodalbail #include <libdllink.h>
406e91bba0SGirish Moodalbail #include <libinetutil.h>
416e91bba0SGirish Moodalbail #include <libipadm.h>
42a73be61aSHans Rosenfeld #include <ipmp.h>
43a73be61aSHans Rosenfeld #include <ipmp_admin.h>
446e91bba0SGirish Moodalbail #include <locale.h>
456e91bba0SGirish Moodalbail #include <netdb.h>
466e91bba0SGirish Moodalbail #include <netinet/in.h>
476e91bba0SGirish Moodalbail #include <ofmt.h>
486e91bba0SGirish Moodalbail #include <stdarg.h>
496e91bba0SGirish Moodalbail #include <stddef.h>
506e91bba0SGirish Moodalbail #include <stdio.h>
516e91bba0SGirish Moodalbail #include <stdlib.h>
526e91bba0SGirish Moodalbail #include <string.h>
536e91bba0SGirish Moodalbail #include <strings.h>
546e91bba0SGirish Moodalbail #include <sys/stat.h>
556e91bba0SGirish Moodalbail #include <sys/types.h>
566e91bba0SGirish Moodalbail #include <zone.h>
57a73be61aSHans Rosenfeld #include <sys/list.h>
58a73be61aSHans Rosenfeld #include <stddef.h>
596e91bba0SGirish Moodalbail
606e91bba0SGirish Moodalbail #define STR_UNKNOWN_VAL "?"
616e91bba0SGirish Moodalbail #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
626e91bba0SGirish Moodalbail LIFC_UNDER_IPMP)
636e91bba0SGirish Moodalbail
64a73be61aSHans Rosenfeld static void do_create_ip_common(int, char **, const char *, uint32_t);
65a73be61aSHans Rosenfeld
666e91bba0SGirish Moodalbail typedef void cmdfunc_t(int, char **, const char *);
67f3f00a64SAndy Fiddaman static cmdfunc_t do_help;
68a73be61aSHans Rosenfeld static cmdfunc_t do_create_ip, do_delete_ip;
69a73be61aSHans Rosenfeld static cmdfunc_t do_create_ipmp, do_add_ipmp, do_remove_ipmp;
70a73be61aSHans Rosenfeld static cmdfunc_t do_disable_if, do_enable_if, do_show_if;
71a73be61aSHans Rosenfeld static cmdfunc_t do_set_ifprop, do_reset_ifprop, do_show_ifprop;
72a73be61aSHans Rosenfeld static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr, do_refresh_addr;
73a73be61aSHans Rosenfeld static cmdfunc_t do_disable_addr, do_enable_addr, do_down_addr, do_up_addr;
74a73be61aSHans Rosenfeld static cmdfunc_t do_set_addrprop, do_reset_addrprop, do_show_addrprop;
75a73be61aSHans Rosenfeld static cmdfunc_t do_set_prop, do_reset_prop, do_show_prop;
766e91bba0SGirish Moodalbail
776e91bba0SGirish Moodalbail typedef struct cmd {
786e91bba0SGirish Moodalbail char *c_name;
796e91bba0SGirish Moodalbail cmdfunc_t *c_fn;
806e91bba0SGirish Moodalbail const char *c_usage;
816e91bba0SGirish Moodalbail } cmd_t;
826e91bba0SGirish Moodalbail
836e91bba0SGirish Moodalbail static cmd_t cmds[] = {
84f3f00a64SAndy Fiddaman { "help", do_help, NULL },
856e91bba0SGirish Moodalbail /* interface management related sub-commands */
86a73be61aSHans Rosenfeld { "create-if", do_create_ip, "\tcreate-if\t[-t] <interface>" },
87a73be61aSHans Rosenfeld { "create-ip", do_create_ip, "\tcreate-ip\t[-t] <interface>" },
88a73be61aSHans Rosenfeld { "delete-if", do_delete_ip, "\tdelete-if\t<interface>\n" },
89a73be61aSHans Rosenfeld { "delete-ip", do_delete_ip, "\tdelete-ip\t<interface>\n" },
90a73be61aSHans Rosenfeld
91a73be61aSHans Rosenfeld { "create-ipmp", do_create_ipmp,
92a73be61aSHans Rosenfeld "\tcreate-ipmp\t[-t] [-i <interface>[,<interface>]...] "
93a73be61aSHans Rosenfeld "<ipmp-interface>" },
94a73be61aSHans Rosenfeld { "delete-ipmp", do_delete_ip,
95a73be61aSHans Rosenfeld "\tdelete-ipmp\t<ipmp-interface>" },
96a73be61aSHans Rosenfeld { "add-ipmp", do_add_ipmp,
97a73be61aSHans Rosenfeld "\tadd-ipmp\t[-t] -i <interface>[,<interface>]... "
98a73be61aSHans Rosenfeld "<ipmp-interface>" },
99a73be61aSHans Rosenfeld { "remove-ipmp", do_remove_ipmp,
100a73be61aSHans Rosenfeld "\tremove-ipmp\t[-t] -i <interface>[,<interface>]... "
101a73be61aSHans Rosenfeld "<ipmp-interface>\n" },
102a73be61aSHans Rosenfeld
103a73be61aSHans Rosenfeld { "disable-if", do_disable_if, "\tdisable-if\t-t <interface>" },
104a73be61aSHans Rosenfeld { "enable-if", do_enable_if, "\tenable-if\t-t <interface>" },
105a73be61aSHans Rosenfeld { "show-if", do_show_if,
1066e91bba0SGirish Moodalbail "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
107a73be61aSHans Rosenfeld
1086e91bba0SGirish Moodalbail { "set-ifprop", do_set_ifprop,
1096e91bba0SGirish Moodalbail "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
110467e811cSToomas Soome "<interface>" },
1116e91bba0SGirish Moodalbail { "reset-ifprop", do_reset_ifprop,
1126e91bba0SGirish Moodalbail "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
1136e91bba0SGirish Moodalbail { "show-ifprop", do_show_ifprop,
1146e91bba0SGirish Moodalbail "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
115467e811cSToomas Soome "\t\t\t[-m <protocol>] [interface]\n" },
1166e91bba0SGirish Moodalbail
1176e91bba0SGirish Moodalbail /* address management related sub-commands */
1186e91bba0SGirish Moodalbail { "create-addr", do_create_addr,
1197bc87895SYuri Pankov "\tcreate-addr\t[-t] -T static [-d] "
1207bc87895SYuri Pankov "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
121b31320a7SChris Fraire "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever]\n"
122b31320a7SChris Fraire "\t\t\t[-1] [-h <hostname>] <addrobj>\n"
1237bc87895SYuri Pankov "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
1247bc87895SYuri Pankov "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
1256e91bba0SGirish Moodalbail { "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
126a73be61aSHans Rosenfeld { "show-addr", do_show_addr,
127a73be61aSHans Rosenfeld "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]" },
128a73be61aSHans Rosenfeld { "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
129a73be61aSHans Rosenfeld { "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>" },
130a73be61aSHans Rosenfeld { "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>" },
131a73be61aSHans Rosenfeld { "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
132a73be61aSHans Rosenfeld { "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>\n" },
133a73be61aSHans Rosenfeld
1346e91bba0SGirish Moodalbail { "set-addrprop", do_set_addrprop,
1356e91bba0SGirish Moodalbail "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
1366e91bba0SGirish Moodalbail { "reset-addrprop", do_reset_addrprop,
1376e91bba0SGirish Moodalbail "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
1386e91bba0SGirish Moodalbail { "show-addrprop", do_show_addrprop,
1396e91bba0SGirish Moodalbail "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
140467e811cSToomas Soome "<addrobj>\n" },
1416e91bba0SGirish Moodalbail
1426e91bba0SGirish Moodalbail /* protocol properties related sub-commands */
143a73be61aSHans Rosenfeld { "set-prop", do_set_prop,
1446e91bba0SGirish Moodalbail "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
145a73be61aSHans Rosenfeld { "reset-prop", do_reset_prop,
1466e91bba0SGirish Moodalbail "\treset-prop\t[-t] -p <prop> <protocol>" },
147a73be61aSHans Rosenfeld { "show-prop", do_show_prop,
1486e91bba0SGirish Moodalbail "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
1498887b57dSGirish Moodalbail " [protocol]" }
1506e91bba0SGirish Moodalbail };
1516e91bba0SGirish Moodalbail
1526e91bba0SGirish Moodalbail static const struct option if_longopts[] = {
1536e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1546e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1556e91bba0SGirish Moodalbail };
1566e91bba0SGirish Moodalbail
1576e91bba0SGirish Moodalbail static const struct option show_prop_longopts[] = {
1586e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'c' },
1596e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1606e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
1616e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1626e91bba0SGirish Moodalbail };
1636e91bba0SGirish Moodalbail
1646e91bba0SGirish Moodalbail static const struct option show_ifprop_longopts[] = {
1656e91bba0SGirish Moodalbail {"module", required_argument, 0, 'm' },
1666e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'c' },
1676e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1686e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
1696e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1706e91bba0SGirish Moodalbail };
1716e91bba0SGirish Moodalbail
1726e91bba0SGirish Moodalbail static const struct option set_prop_longopts[] = {
1736e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1746e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1756e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1766e91bba0SGirish Moodalbail };
1776e91bba0SGirish Moodalbail
1786e91bba0SGirish Moodalbail static const struct option set_ifprop_longopts[] = {
1796e91bba0SGirish Moodalbail {"module", required_argument, 0, 'm' },
1806e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1816e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1826e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1836e91bba0SGirish Moodalbail };
1846e91bba0SGirish Moodalbail
1856e91bba0SGirish Moodalbail static const struct option addr_misc_longopts[] = {
1866e91bba0SGirish Moodalbail {"inform", no_argument, 0, 'i' },
1876e91bba0SGirish Moodalbail {"release", no_argument, 0, 'r' },
1886e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1896e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1906e91bba0SGirish Moodalbail };
1916e91bba0SGirish Moodalbail
1926e91bba0SGirish Moodalbail static const struct option addr_longopts[] = {
1936e91bba0SGirish Moodalbail {"address", required_argument, 0, 'a' },
1946e91bba0SGirish Moodalbail {"down", no_argument, 0, 'd' },
1956e91bba0SGirish Moodalbail {"interface-id", required_argument, 0, 'i' },
196b31320a7SChris Fraire {"primary", no_argument, 0, '1' },
1976e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
198b31320a7SChris Fraire {"reqhost", required_argument, 0, 'h' },
1996e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
2006e91bba0SGirish Moodalbail {"type", required_argument, 0, 'T' },
2016e91bba0SGirish Moodalbail {"wait", required_argument, 0, 'w' },
2026e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
2036e91bba0SGirish Moodalbail };
2046e91bba0SGirish Moodalbail
2056e91bba0SGirish Moodalbail static const struct option show_addr_longopts[] = {
2066e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'p' },
2076e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
2086e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
2096e91bba0SGirish Moodalbail };
2106e91bba0SGirish Moodalbail
2116e91bba0SGirish Moodalbail static const struct option show_if_longopts[] = {
2126e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'p' },
2136e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
2146e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
2156e91bba0SGirish Moodalbail };
2166e91bba0SGirish Moodalbail
2176e91bba0SGirish Moodalbail /* callback functions to print show-* subcommands output */
2186e91bba0SGirish Moodalbail static ofmt_cb_t print_prop_cb;
2196e91bba0SGirish Moodalbail static ofmt_cb_t print_sa_cb;
2206e91bba0SGirish Moodalbail static ofmt_cb_t print_si_cb;
2216e91bba0SGirish Moodalbail
2226e91bba0SGirish Moodalbail /* structures for 'ipadm show-*' subcommands */
2236e91bba0SGirish Moodalbail typedef enum {
2246e91bba0SGirish Moodalbail IPADM_PROPFIELD_IFNAME,
2256e91bba0SGirish Moodalbail IPADM_PROPFIELD_PROTO,
2266e91bba0SGirish Moodalbail IPADM_PROPFIELD_ADDROBJ,
2276e91bba0SGirish Moodalbail IPADM_PROPFIELD_PROPERTY,
2286e91bba0SGirish Moodalbail IPADM_PROPFIELD_PERM,
2296e91bba0SGirish Moodalbail IPADM_PROPFIELD_CURRENT,
2306e91bba0SGirish Moodalbail IPADM_PROPFIELD_PERSISTENT,
2316e91bba0SGirish Moodalbail IPADM_PROPFIELD_DEFAULT,
2326e91bba0SGirish Moodalbail IPADM_PROPFIELD_POSSIBLE
2336e91bba0SGirish Moodalbail } ipadm_propfield_index_t;
2346e91bba0SGirish Moodalbail
2356e91bba0SGirish Moodalbail static ofmt_field_t intfprop_fields[] = {
2366e91bba0SGirish Moodalbail /* name, field width, index, callback */
2376e91bba0SGirish Moodalbail { "IFNAME", 12, IPADM_PROPFIELD_IFNAME, print_prop_cb},
2386e91bba0SGirish Moodalbail { "PROPERTY", 16, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
2396e91bba0SGirish Moodalbail { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
2406e91bba0SGirish Moodalbail { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
2416e91bba0SGirish Moodalbail { "CURRENT", 11, IPADM_PROPFIELD_CURRENT, print_prop_cb},
2426e91bba0SGirish Moodalbail { "PERSISTENT", 11, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
2436e91bba0SGirish Moodalbail { "DEFAULT", 11, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
2446e91bba0SGirish Moodalbail { "POSSIBLE", 16, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
2456e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
2466e91bba0SGirish Moodalbail };
2476e91bba0SGirish Moodalbail
2486e91bba0SGirish Moodalbail
2496e91bba0SGirish Moodalbail static ofmt_field_t modprop_fields[] = {
2506e91bba0SGirish Moodalbail /* name, field width, index, callback */
2516e91bba0SGirish Moodalbail { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
2526e91bba0SGirish Moodalbail { "PROPERTY", 22, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
2536e91bba0SGirish Moodalbail { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
2546e91bba0SGirish Moodalbail { "CURRENT", 13, IPADM_PROPFIELD_CURRENT, print_prop_cb},
2556e91bba0SGirish Moodalbail { "PERSISTENT", 13, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
2566e91bba0SGirish Moodalbail { "DEFAULT", 13, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
2576e91bba0SGirish Moodalbail { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
2586e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
2596e91bba0SGirish Moodalbail };
2606e91bba0SGirish Moodalbail
2616e91bba0SGirish Moodalbail static ofmt_field_t addrprop_fields[] = {
2626e91bba0SGirish Moodalbail /* name, field width, index, callback */
2636e91bba0SGirish Moodalbail { "ADDROBJ", 18, IPADM_PROPFIELD_ADDROBJ, print_prop_cb},
2646e91bba0SGirish Moodalbail { "PROPERTY", 11, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
2656e91bba0SGirish Moodalbail { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
2666e91bba0SGirish Moodalbail { "CURRENT", 16, IPADM_PROPFIELD_CURRENT, print_prop_cb},
2676e91bba0SGirish Moodalbail { "PERSISTENT", 16, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
2686e91bba0SGirish Moodalbail { "DEFAULT", 16, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
2696e91bba0SGirish Moodalbail { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
2706e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
2716e91bba0SGirish Moodalbail };
2726e91bba0SGirish Moodalbail
2736e91bba0SGirish Moodalbail typedef struct show_prop_state {
2746e91bba0SGirish Moodalbail char sps_ifname[LIFNAMSIZ];
2756e91bba0SGirish Moodalbail char sps_aobjname[IPADM_AOBJSIZ];
2766e91bba0SGirish Moodalbail const char *sps_pname;
2776e91bba0SGirish Moodalbail uint_t sps_proto;
2786e91bba0SGirish Moodalbail char *sps_propval;
2796e91bba0SGirish Moodalbail nvlist_t *sps_proplist;
2806e91bba0SGirish Moodalbail boolean_t sps_parsable;
2816e91bba0SGirish Moodalbail boolean_t sps_addrprop;
2826e91bba0SGirish Moodalbail boolean_t sps_ifprop;
2836e91bba0SGirish Moodalbail boolean_t sps_modprop;
2846e91bba0SGirish Moodalbail ipadm_status_t sps_status;
2856e91bba0SGirish Moodalbail ipadm_status_t sps_retstatus;
2866e91bba0SGirish Moodalbail ofmt_handle_t sps_ofmt;
2876e91bba0SGirish Moodalbail } show_prop_state_t;
2886e91bba0SGirish Moodalbail
2896e91bba0SGirish Moodalbail typedef struct show_addr_state {
2906e91bba0SGirish Moodalbail boolean_t sa_parsable;
2916e91bba0SGirish Moodalbail boolean_t sa_persist;
2926e91bba0SGirish Moodalbail ofmt_handle_t sa_ofmt;
2936e91bba0SGirish Moodalbail } show_addr_state_t;
2946e91bba0SGirish Moodalbail
2956e91bba0SGirish Moodalbail typedef struct show_if_state {
2966e91bba0SGirish Moodalbail boolean_t si_parsable;
2976e91bba0SGirish Moodalbail ofmt_handle_t si_ofmt;
2986e91bba0SGirish Moodalbail } show_if_state_t;
2996e91bba0SGirish Moodalbail
3006e91bba0SGirish Moodalbail typedef struct show_addr_args_s {
3016e91bba0SGirish Moodalbail show_addr_state_t *sa_state;
3026e91bba0SGirish Moodalbail ipadm_addr_info_t *sa_info;
3036e91bba0SGirish Moodalbail } show_addr_args_t;
3046e91bba0SGirish Moodalbail
3056e91bba0SGirish Moodalbail typedef struct show_if_args_s {
3066e91bba0SGirish Moodalbail show_if_state_t *si_state;
307a73be61aSHans Rosenfeld ipadm_if_info_t *si_info;
3086e91bba0SGirish Moodalbail } show_if_args_t;
3096e91bba0SGirish Moodalbail
3106e91bba0SGirish Moodalbail typedef enum {
3116e91bba0SGirish Moodalbail SA_ADDROBJ,
3126e91bba0SGirish Moodalbail SA_TYPE,
3136e91bba0SGirish Moodalbail SA_STATE,
3146e91bba0SGirish Moodalbail SA_CURRENT,
3156e91bba0SGirish Moodalbail SA_PERSISTENT,
3166e91bba0SGirish Moodalbail SA_ADDR
3176e91bba0SGirish Moodalbail } sa_field_index_t;
3186e91bba0SGirish Moodalbail
3196e91bba0SGirish Moodalbail typedef enum {
3206e91bba0SGirish Moodalbail SI_IFNAME,
321a73be61aSHans Rosenfeld SI_IFCLASS,
3226e91bba0SGirish Moodalbail SI_STATE,
3236e91bba0SGirish Moodalbail SI_CURRENT,
3246e91bba0SGirish Moodalbail SI_PERSISTENT
3256e91bba0SGirish Moodalbail } si_field_index_t;
3266e91bba0SGirish Moodalbail
3276e91bba0SGirish Moodalbail static ofmt_field_t show_addr_fields[] = {
3286e91bba0SGirish Moodalbail /* name, field width, id, callback */
3296e91bba0SGirish Moodalbail { "ADDROBJ", 18, SA_ADDROBJ, print_sa_cb},
3306e91bba0SGirish Moodalbail { "TYPE", 9, SA_TYPE, print_sa_cb},
3316e91bba0SGirish Moodalbail { "STATE", 13, SA_STATE, print_sa_cb},
3326e91bba0SGirish Moodalbail { "CURRENT", 8, SA_CURRENT, print_sa_cb},
3336e91bba0SGirish Moodalbail { "PERSISTENT", 11, SA_PERSISTENT, print_sa_cb},
3346e91bba0SGirish Moodalbail { "ADDR", 46, SA_ADDR, print_sa_cb},
3356e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
3366e91bba0SGirish Moodalbail };
3376e91bba0SGirish Moodalbail
3386e91bba0SGirish Moodalbail static ofmt_field_t show_if_fields[] = {
3396e91bba0SGirish Moodalbail /* name, field width, id, callback */
3406e91bba0SGirish Moodalbail { "IFNAME", 11, SI_IFNAME, print_si_cb},
341a73be61aSHans Rosenfeld { "CLASS", 10, SI_IFCLASS, print_si_cb},
3426e91bba0SGirish Moodalbail { "STATE", 9, SI_STATE, print_si_cb},
343550b6e40SSowmini Varadhan { "CURRENT", 13, SI_CURRENT, print_si_cb},
3446e91bba0SGirish Moodalbail { "PERSISTENT", 11, SI_PERSISTENT, print_si_cb},
3456e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
3466e91bba0SGirish Moodalbail };
3476e91bba0SGirish Moodalbail
3486e91bba0SGirish Moodalbail #define IPADM_ALL_BITS ((uint_t)-1)
3496e91bba0SGirish Moodalbail typedef struct intf_mask {
3506e91bba0SGirish Moodalbail char *name;
3516e91bba0SGirish Moodalbail uint64_t bits;
3526e91bba0SGirish Moodalbail uint64_t mask;
3536e91bba0SGirish Moodalbail } fmask_t;
3546e91bba0SGirish Moodalbail
355a73be61aSHans Rosenfeld typedef enum {
356a73be61aSHans Rosenfeld IPMP_ADD_MEMBER,
357a73be61aSHans Rosenfeld IPMP_REMOVE_MEMBER
358a73be61aSHans Rosenfeld } ipmp_action_t;
359a73be61aSHans Rosenfeld
3606e91bba0SGirish Moodalbail /*
3616e91bba0SGirish Moodalbail * Handle to libipadm. Opened in main() before the sub-command specific
3626e91bba0SGirish Moodalbail * function is called and is closed before the program exits.
3636e91bba0SGirish Moodalbail */
3646e91bba0SGirish Moodalbail ipadm_handle_t iph = NULL;
3656e91bba0SGirish Moodalbail
3666e91bba0SGirish Moodalbail /*
3676e91bba0SGirish Moodalbail * Opaque ipadm address object. Used by all the address management subcommands.
3686e91bba0SGirish Moodalbail */
3696e91bba0SGirish Moodalbail ipadm_addrobj_t ipaddr = NULL;
3706e91bba0SGirish Moodalbail
3716e91bba0SGirish Moodalbail static char *progname;
3726e91bba0SGirish Moodalbail
373467e811cSToomas Soome
374467e811cSToomas Soome static void warn(const char *, ...);
375467e811cSToomas Soome static void die(const char *, ...) __NORETURN;
376467e811cSToomas Soome static void die_opterr(int, int, const char *) __NORETURN;
3776e91bba0SGirish Moodalbail static void warn_ipadmerr(ipadm_status_t, const char *, ...);
378467e811cSToomas Soome static void ipadm_check_propstr(const char *, boolean_t, const char *);
379467e811cSToomas Soome static void process_misc_addrargs(int, char **, const char *, int *,
3806e91bba0SGirish Moodalbail uint32_t *);
381a73be61aSHans Rosenfeld static void do_action_ipmp(char *, ipadm_ipmp_members_t *, ipmp_action_t,
382a73be61aSHans Rosenfeld uint32_t);
383a73be61aSHans Rosenfeld
3846e91bba0SGirish Moodalbail
3856e91bba0SGirish Moodalbail static void
usage(int ret)386f3f00a64SAndy Fiddaman usage(int ret)
3876e91bba0SGirish Moodalbail {
3886e91bba0SGirish Moodalbail int i;
3896e91bba0SGirish Moodalbail cmd_t *cmdp;
3906e91bba0SGirish Moodalbail
3916e91bba0SGirish Moodalbail (void) fprintf(stderr,
3926e91bba0SGirish Moodalbail gettext("usage: ipadm <subcommand> <args> ...\n"));
3936e91bba0SGirish Moodalbail for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
3946e91bba0SGirish Moodalbail cmdp = &cmds[i];
3956e91bba0SGirish Moodalbail if (cmdp->c_usage != NULL)
3966e91bba0SGirish Moodalbail (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
3976e91bba0SGirish Moodalbail }
3986e91bba0SGirish Moodalbail
3996e91bba0SGirish Moodalbail ipadm_destroy_addrobj(ipaddr);
4006e91bba0SGirish Moodalbail ipadm_close(iph);
401f3f00a64SAndy Fiddaman exit(ret);
402f3f00a64SAndy Fiddaman }
403f3f00a64SAndy Fiddaman
404f3f00a64SAndy Fiddaman static void
do_help(int argc __unused,char ** argv __unused,const char * use __unused)405f3f00a64SAndy Fiddaman do_help(int argc __unused, char **argv __unused, const char *use __unused)
406f3f00a64SAndy Fiddaman {
407f3f00a64SAndy Fiddaman usage(0);
4086e91bba0SGirish Moodalbail }
4096e91bba0SGirish Moodalbail
4106e91bba0SGirish Moodalbail int
main(int argc,char * argv[])4116e91bba0SGirish Moodalbail main(int argc, char *argv[])
4126e91bba0SGirish Moodalbail {
4136e91bba0SGirish Moodalbail int i;
4146e91bba0SGirish Moodalbail cmd_t *cmdp;
4156e91bba0SGirish Moodalbail ipadm_status_t status;
4166e91bba0SGirish Moodalbail
4176e91bba0SGirish Moodalbail (void) setlocale(LC_ALL, "");
4186e91bba0SGirish Moodalbail (void) textdomain(TEXT_DOMAIN);
4196e91bba0SGirish Moodalbail
4206e91bba0SGirish Moodalbail if ((progname = strrchr(argv[0], '/')) == NULL)
4216e91bba0SGirish Moodalbail progname = argv[0];
4226e91bba0SGirish Moodalbail else
4236e91bba0SGirish Moodalbail progname++;
4246e91bba0SGirish Moodalbail
425f3f00a64SAndy Fiddaman if (argc < 2) {
426f3f00a64SAndy Fiddaman argv[1] = "show-addr";
427f3f00a64SAndy Fiddaman argc = 2;
428f3f00a64SAndy Fiddaman }
4296e91bba0SGirish Moodalbail
4306e91bba0SGirish Moodalbail status = ipadm_open(&iph, 0);
4316e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
4326e91bba0SGirish Moodalbail die("Could not open handle to library - %s",
4336e91bba0SGirish Moodalbail ipadm_status2str(status));
4346e91bba0SGirish Moodalbail }
4356e91bba0SGirish Moodalbail
4366e91bba0SGirish Moodalbail for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
4376e91bba0SGirish Moodalbail cmdp = &cmds[i];
4386e91bba0SGirish Moodalbail if (strcmp(argv[1], cmdp->c_name) == 0) {
4396e91bba0SGirish Moodalbail cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
4406e91bba0SGirish Moodalbail ipadm_destroy_addrobj(ipaddr);
4416e91bba0SGirish Moodalbail ipadm_close(iph);
4426e91bba0SGirish Moodalbail exit(0);
4436e91bba0SGirish Moodalbail }
4446e91bba0SGirish Moodalbail }
4456e91bba0SGirish Moodalbail
4466e91bba0SGirish Moodalbail (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
4476e91bba0SGirish Moodalbail progname, argv[1]);
448f3f00a64SAndy Fiddaman usage(1);
4496e91bba0SGirish Moodalbail
4506e91bba0SGirish Moodalbail return (0);
4516e91bba0SGirish Moodalbail }
4526e91bba0SGirish Moodalbail
4536e91bba0SGirish Moodalbail /*
454a73be61aSHans Rosenfeld * Create regular IP interface or IPMP group interface
4556e91bba0SGirish Moodalbail */
4566e91bba0SGirish Moodalbail static void
do_create_ip_common(int argc,char * argv[],const char * use,uint32_t flags)457a73be61aSHans Rosenfeld do_create_ip_common(int argc, char *argv[], const char *use, uint32_t flags)
4586e91bba0SGirish Moodalbail {
4596e91bba0SGirish Moodalbail ipadm_status_t status;
4606e91bba0SGirish Moodalbail int option;
4616e91bba0SGirish Moodalbail
4626e91bba0SGirish Moodalbail opterr = 0;
463a73be61aSHans Rosenfeld while ((option = getopt_long(argc, argv,
464a73be61aSHans Rosenfeld ":t", if_longopts, NULL)) != -1) {
4656e91bba0SGirish Moodalbail switch (option) {
4666e91bba0SGirish Moodalbail case 't':
4676e91bba0SGirish Moodalbail /*
4686e91bba0SGirish Moodalbail * "ifconfig" mode - plumb interface, but do not
4696e91bba0SGirish Moodalbail * restore settings that may exist in db.
4706e91bba0SGirish Moodalbail */
4716e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
4726e91bba0SGirish Moodalbail break;
4736e91bba0SGirish Moodalbail default:
4746e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
4756e91bba0SGirish Moodalbail }
4766e91bba0SGirish Moodalbail }
477a73be61aSHans Rosenfeld if (optind != (argc - 1)) {
478a73be61aSHans Rosenfeld if (use != NULL)
479a73be61aSHans Rosenfeld die("usage: %s", use);
480a73be61aSHans Rosenfeld else
481a73be61aSHans Rosenfeld die(NULL);
482a73be61aSHans Rosenfeld }
4836e91bba0SGirish Moodalbail status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
4846e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
4856e91bba0SGirish Moodalbail die("Could not create %s : %s",
4866e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
4876e91bba0SGirish Moodalbail }
4886e91bba0SGirish Moodalbail }
4896e91bba0SGirish Moodalbail
490a73be61aSHans Rosenfeld /*
491a73be61aSHans Rosenfeld * Helpers to parse options into ipadm_ipmp_members_t list, and to free it.
492a73be61aSHans Rosenfeld */
493a73be61aSHans Rosenfeld static ipadm_ipmp_members_t *
get_ipmp_members(int argc,char * argv[],const char * use,uint32_t * flags)494a73be61aSHans Rosenfeld get_ipmp_members(int argc, char *argv[], const char *use, uint32_t *flags)
495a73be61aSHans Rosenfeld {
496a73be61aSHans Rosenfeld ipadm_ipmp_members_t *members = NULL;
497a73be61aSHans Rosenfeld ipadm_ipmp_member_t *member;
498a73be61aSHans Rosenfeld char *ifname;
499a73be61aSHans Rosenfeld int option;
500a73be61aSHans Rosenfeld
501a73be61aSHans Rosenfeld
502a73be61aSHans Rosenfeld opterr = 0;
503a73be61aSHans Rosenfeld while ((option = getopt_long(argc, argv, ":i:", if_longopts, NULL)) !=
504a73be61aSHans Rosenfeld -1) {
505a73be61aSHans Rosenfeld switch (option) {
506a73be61aSHans Rosenfeld case 't':
507a73be61aSHans Rosenfeld *flags &= ~IPADM_OPT_PERSIST;
508a73be61aSHans Rosenfeld break;
509a73be61aSHans Rosenfeld case 'i':
510a73be61aSHans Rosenfeld if (members == NULL) {
511a73be61aSHans Rosenfeld members = calloc(1,
512a73be61aSHans Rosenfeld sizeof (ipadm_ipmp_members_t));
513a73be61aSHans Rosenfeld if (members == NULL)
514a73be61aSHans Rosenfeld die("insufficient memory");
515a73be61aSHans Rosenfeld list_create(members,
516a73be61aSHans Rosenfeld sizeof (ipadm_ipmp_member_t),
517a73be61aSHans Rosenfeld offsetof(ipadm_ipmp_member_t, node));
518a73be61aSHans Rosenfeld }
519a73be61aSHans Rosenfeld
520a73be61aSHans Rosenfeld for (ifname = strtok(optarg, ",");
521a73be61aSHans Rosenfeld ifname != NULL;
522a73be61aSHans Rosenfeld ifname = strtok(NULL, ",")) {
523a73be61aSHans Rosenfeld if ((member = calloc(1,
524a73be61aSHans Rosenfeld sizeof (ipadm_ipmp_member_t))) == NULL)
525a73be61aSHans Rosenfeld die("insufficient memory");
526a73be61aSHans Rosenfeld
527a73be61aSHans Rosenfeld if (strlcpy(member->if_name, ifname,
528a73be61aSHans Rosenfeld sizeof (member->if_name)) >= LIFNAMSIZ)
529a73be61aSHans Rosenfeld die("Incorrect length of interface "
530a73be61aSHans Rosenfeld "name: %s", ifname);
531a73be61aSHans Rosenfeld
532a73be61aSHans Rosenfeld list_insert_tail(members, member);
533a73be61aSHans Rosenfeld }
534a73be61aSHans Rosenfeld break;
535a73be61aSHans Rosenfeld default:
536a73be61aSHans Rosenfeld die_opterr(optopt, option, use);
537a73be61aSHans Rosenfeld }
538a73be61aSHans Rosenfeld }
539a73be61aSHans Rosenfeld
540a73be61aSHans Rosenfeld if (optind != (argc - 1))
541a73be61aSHans Rosenfeld die("Usage: %s", use);
542a73be61aSHans Rosenfeld
543a73be61aSHans Rosenfeld if (members != NULL && list_is_empty(members)) {
544a73be61aSHans Rosenfeld free(members);
545a73be61aSHans Rosenfeld members = NULL;
546a73be61aSHans Rosenfeld }
547a73be61aSHans Rosenfeld
548a73be61aSHans Rosenfeld return (members);
549a73be61aSHans Rosenfeld }
550a73be61aSHans Rosenfeld
551a73be61aSHans Rosenfeld static void
free_ipmp_members(ipadm_ipmp_members_t * members)552a73be61aSHans Rosenfeld free_ipmp_members(ipadm_ipmp_members_t *members)
553a73be61aSHans Rosenfeld {
554a73be61aSHans Rosenfeld ipadm_ipmp_member_t *member;
555a73be61aSHans Rosenfeld
556a73be61aSHans Rosenfeld while ((member = list_remove_head(members)) != NULL)
557a73be61aSHans Rosenfeld free(member);
558a73be61aSHans Rosenfeld
559a73be61aSHans Rosenfeld list_destroy(members);
560a73be61aSHans Rosenfeld
561a73be61aSHans Rosenfeld free(members);
562a73be61aSHans Rosenfeld }
563a73be61aSHans Rosenfeld
564a73be61aSHans Rosenfeld /*
565a73be61aSHans Rosenfeld * Create an IPMP group interface for which no saved configuration
566a73be61aSHans Rosenfeld * exists in the persistent store.
567a73be61aSHans Rosenfeld */
568a73be61aSHans Rosenfeld static void
do_create_ipmp(int argc,char * argv[],const char * use)569a73be61aSHans Rosenfeld do_create_ipmp(int argc, char *argv[], const char *use)
570a73be61aSHans Rosenfeld {
571a73be61aSHans Rosenfeld uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE | IPADM_OPT_IPMP;
572a73be61aSHans Rosenfeld ipadm_ipmp_members_t *members = NULL;
573a73be61aSHans Rosenfeld ipmp_handle_t ipmp_handle;
574a73be61aSHans Rosenfeld int retval;
575a73be61aSHans Rosenfeld
576a73be61aSHans Rosenfeld retval = ipmp_open(&ipmp_handle);
577a73be61aSHans Rosenfeld if (retval != IPMP_SUCCESS) {
578a73be61aSHans Rosenfeld die("Could not create IPMP handle: %s",
579a73be61aSHans Rosenfeld ipadm_status2str(retval));
580a73be61aSHans Rosenfeld }
581a73be61aSHans Rosenfeld
582a73be61aSHans Rosenfeld retval = ipmp_ping_daemon(ipmp_handle);
583a73be61aSHans Rosenfeld ipmp_close(ipmp_handle);
584a73be61aSHans Rosenfeld
585a73be61aSHans Rosenfeld if (retval != IPMP_SUCCESS) {
586a73be61aSHans Rosenfeld die("Cannot ping in.mpathd: %s", ipmp_errmsg(retval));
587a73be61aSHans Rosenfeld }
588a73be61aSHans Rosenfeld
589a73be61aSHans Rosenfeld members = get_ipmp_members(argc, argv, use, &flags);
590a73be61aSHans Rosenfeld
591a73be61aSHans Rosenfeld do_create_ip_common(argc, argv, use, flags);
592a73be61aSHans Rosenfeld
593a73be61aSHans Rosenfeld if (members != NULL) {
594a73be61aSHans Rosenfeld do_action_ipmp(argv[optind], members, IPMP_ADD_MEMBER, flags);
595a73be61aSHans Rosenfeld free_ipmp_members(members);
596a73be61aSHans Rosenfeld }
597a73be61aSHans Rosenfeld }
598a73be61aSHans Rosenfeld
599a73be61aSHans Rosenfeld static void
do_add_ipmp(int argc,char * argv[],const char * use)600a73be61aSHans Rosenfeld do_add_ipmp(int argc, char *argv[], const char *use)
601a73be61aSHans Rosenfeld {
602a73be61aSHans Rosenfeld uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE;
603a73be61aSHans Rosenfeld ipadm_ipmp_members_t *members;
604a73be61aSHans Rosenfeld
605a73be61aSHans Rosenfeld members = get_ipmp_members(argc, argv, use, &flags);
606a73be61aSHans Rosenfeld
607a73be61aSHans Rosenfeld if (members == NULL)
608a73be61aSHans Rosenfeld die_opterr(optopt, ':', use);
609a73be61aSHans Rosenfeld
610a73be61aSHans Rosenfeld do_action_ipmp(argv[optind], members, IPMP_ADD_MEMBER, flags);
611a73be61aSHans Rosenfeld free_ipmp_members(members);
612a73be61aSHans Rosenfeld }
613a73be61aSHans Rosenfeld
614a73be61aSHans Rosenfeld static void
do_remove_ipmp(int argc,char * argv[],const char * use)615a73be61aSHans Rosenfeld do_remove_ipmp(int argc, char *argv[], const char *use)
616a73be61aSHans Rosenfeld {
617a73be61aSHans Rosenfeld uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE;
618a73be61aSHans Rosenfeld ipadm_ipmp_members_t *members;
619a73be61aSHans Rosenfeld
620a73be61aSHans Rosenfeld members = get_ipmp_members(argc, argv, use, &flags);
621a73be61aSHans Rosenfeld
622a73be61aSHans Rosenfeld if (members == NULL)
623a73be61aSHans Rosenfeld die_opterr(optopt, ':', use);
624a73be61aSHans Rosenfeld
625a73be61aSHans Rosenfeld do_action_ipmp(argv[optind], members, IPMP_REMOVE_MEMBER, flags);
626a73be61aSHans Rosenfeld free_ipmp_members(members);
627a73be61aSHans Rosenfeld }
628a73be61aSHans Rosenfeld
629a73be61aSHans Rosenfeld static void
do_action_ipmp(char * ipmp,ipadm_ipmp_members_t * members,ipmp_action_t action,uint32_t flags)630a73be61aSHans Rosenfeld do_action_ipmp(char *ipmp, ipadm_ipmp_members_t *members, ipmp_action_t action,
631a73be61aSHans Rosenfeld uint32_t flags)
632a73be61aSHans Rosenfeld {
633a73be61aSHans Rosenfeld ipadm_status_t (*func)(ipadm_handle_t, const char *, const char *,
634a73be61aSHans Rosenfeld uint32_t);
635a73be61aSHans Rosenfeld ipadm_status_t status;
636a73be61aSHans Rosenfeld ipadm_ipmp_member_t *member;
637a73be61aSHans Rosenfeld char *ifname;
638a73be61aSHans Rosenfeld const char *msg;
639a73be61aSHans Rosenfeld
640a73be61aSHans Rosenfeld if (action == IPMP_ADD_MEMBER) {
641a73be61aSHans Rosenfeld func = ipadm_add_ipmp_member;
642a73be61aSHans Rosenfeld msg = "Cannot add interface '%s' to IPMP interface '%s': %s";
643a73be61aSHans Rosenfeld } else {
644a73be61aSHans Rosenfeld func = ipadm_remove_ipmp_member;
645a73be61aSHans Rosenfeld msg = "Cannot remove interface '%s' from IPMP interface '%s': "
646a73be61aSHans Rosenfeld "%s";
647a73be61aSHans Rosenfeld }
648a73be61aSHans Rosenfeld
649a73be61aSHans Rosenfeld while ((member = list_remove_head(members)) != NULL) {
650a73be61aSHans Rosenfeld ifname = member->if_name;
651a73be61aSHans Rosenfeld
652a73be61aSHans Rosenfeld status = func(iph, ipmp, ifname, flags);
653a73be61aSHans Rosenfeld if (status != IPADM_SUCCESS)
654a73be61aSHans Rosenfeld die(msg, ifname, ipmp, ipadm_status2str(status));
655a73be61aSHans Rosenfeld }
656a73be61aSHans Rosenfeld }
657a73be61aSHans Rosenfeld
658a73be61aSHans Rosenfeld /*
659a73be61aSHans Rosenfeld * Create an IP interface for which no saved configuration exists in the
660a73be61aSHans Rosenfeld * persistent store.
661a73be61aSHans Rosenfeld */
662a73be61aSHans Rosenfeld static void
do_create_ip(int argc,char * argv[],const char * use)663a73be61aSHans Rosenfeld do_create_ip(int argc, char *argv[], const char *use)
664a73be61aSHans Rosenfeld {
665a73be61aSHans Rosenfeld do_create_ip_common(argc, argv, use,
666a73be61aSHans Rosenfeld IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE);
667a73be61aSHans Rosenfeld }
668a73be61aSHans Rosenfeld
6696e91bba0SGirish Moodalbail /*
6706e91bba0SGirish Moodalbail * Enable an IP interface based on the persistent configuration for
6716e91bba0SGirish Moodalbail * that interface.
6726e91bba0SGirish Moodalbail */
6736e91bba0SGirish Moodalbail static void
do_enable_if(int argc,char * argv[],const char * use)6746e91bba0SGirish Moodalbail do_enable_if(int argc, char *argv[], const char *use)
6756e91bba0SGirish Moodalbail {
6766e91bba0SGirish Moodalbail ipadm_status_t status;
6776e91bba0SGirish Moodalbail int index;
678467e811cSToomas Soome uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
6796e91bba0SGirish Moodalbail
6806e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
6816e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
6826e91bba0SGirish Moodalbail die("persistent operation not supported for enable-if");
6836e91bba0SGirish Moodalbail status = ipadm_enable_if(iph, argv[index], flags);
6846e91bba0SGirish Moodalbail if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
6856e91bba0SGirish Moodalbail warn_ipadmerr(status, "");
6866e91bba0SGirish Moodalbail } else if (status != IPADM_SUCCESS) {
6876e91bba0SGirish Moodalbail die("Could not enable %s : %s",
6886e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
6896e91bba0SGirish Moodalbail }
6906e91bba0SGirish Moodalbail }
6916e91bba0SGirish Moodalbail
6926e91bba0SGirish Moodalbail /*
6936e91bba0SGirish Moodalbail * Remove an IP interface from both active and persistent configuration.
6946e91bba0SGirish Moodalbail */
6956e91bba0SGirish Moodalbail static void
do_delete_ip(int argc,char * argv[],const char * use)696a73be61aSHans Rosenfeld do_delete_ip(int argc, char *argv[], const char *use)
6976e91bba0SGirish Moodalbail {
6986e91bba0SGirish Moodalbail ipadm_status_t status;
6996e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
7006e91bba0SGirish Moodalbail
7016e91bba0SGirish Moodalbail if (argc != 2)
7026e91bba0SGirish Moodalbail die("Usage: %s", use);
7036e91bba0SGirish Moodalbail
7046e91bba0SGirish Moodalbail status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
7056e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
7066e91bba0SGirish Moodalbail die("Could not delete %s: %s",
7076e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
7086e91bba0SGirish Moodalbail }
7096e91bba0SGirish Moodalbail }
7106e91bba0SGirish Moodalbail
7116e91bba0SGirish Moodalbail /*
7126e91bba0SGirish Moodalbail * Disable an IP interface by removing it from active configuration.
7136e91bba0SGirish Moodalbail */
7146e91bba0SGirish Moodalbail static void
do_disable_if(int argc,char * argv[],const char * use)7156e91bba0SGirish Moodalbail do_disable_if(int argc, char *argv[], const char *use)
7166e91bba0SGirish Moodalbail {
7176e91bba0SGirish Moodalbail ipadm_status_t status;
7186e91bba0SGirish Moodalbail int index;
719467e811cSToomas Soome uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
7206e91bba0SGirish Moodalbail
7216e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
7226e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
7236e91bba0SGirish Moodalbail die("persistent operation not supported for disable-if");
7246e91bba0SGirish Moodalbail status = ipadm_disable_if(iph, argv[index], flags);
7256e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
7266e91bba0SGirish Moodalbail die("Could not disable %s: %s",
7276e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
7286e91bba0SGirish Moodalbail }
7296e91bba0SGirish Moodalbail }
7306e91bba0SGirish Moodalbail
7316e91bba0SGirish Moodalbail /*
7328c8556f9SYuri Pankov * Print individual columns for the show-*prop subcommands.
7336e91bba0SGirish Moodalbail */
7346e91bba0SGirish Moodalbail static void
print_prop(show_prop_state_t * statep,uint_t flags,char * buf,size_t bufsize)7356e91bba0SGirish Moodalbail print_prop(show_prop_state_t *statep, uint_t flags, char *buf, size_t bufsize)
7366e91bba0SGirish Moodalbail {
7376e91bba0SGirish Moodalbail const char *prop_name = statep->sps_pname;
7386e91bba0SGirish Moodalbail char *ifname = statep->sps_ifname;
7396e91bba0SGirish Moodalbail char *propval = statep->sps_propval;
7406e91bba0SGirish Moodalbail uint_t proto = statep->sps_proto;
7416e91bba0SGirish Moodalbail size_t propsize = MAXPROPVALLEN;
7426e91bba0SGirish Moodalbail ipadm_status_t status;
7436e91bba0SGirish Moodalbail
7446e91bba0SGirish Moodalbail if (statep->sps_ifprop) {
7456e91bba0SGirish Moodalbail status = ipadm_get_ifprop(iph, ifname, prop_name, propval,
7466e91bba0SGirish Moodalbail &propsize, proto, flags);
7476e91bba0SGirish Moodalbail } else if (statep->sps_modprop) {
7486e91bba0SGirish Moodalbail status = ipadm_get_prop(iph, prop_name, propval, &propsize,
7496e91bba0SGirish Moodalbail proto, flags);
7506e91bba0SGirish Moodalbail } else {
7516e91bba0SGirish Moodalbail status = ipadm_get_addrprop(iph, prop_name, propval, &propsize,
7526e91bba0SGirish Moodalbail statep->sps_aobjname, flags);
7536e91bba0SGirish Moodalbail }
7546e91bba0SGirish Moodalbail
7556e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
7568c8556f9SYuri Pankov if ((status == IPADM_NOTFOUND && (flags & IPADM_OPT_PERSIST)) ||
7578c8556f9SYuri Pankov status == IPADM_ENXIO) {
7586e91bba0SGirish Moodalbail propval[0] = '\0';
7596e91bba0SGirish Moodalbail goto cont;
7606e91bba0SGirish Moodalbail }
7616e91bba0SGirish Moodalbail statep->sps_status = status;
7626e91bba0SGirish Moodalbail statep->sps_retstatus = status;
7636e91bba0SGirish Moodalbail return;
7646e91bba0SGirish Moodalbail }
7656e91bba0SGirish Moodalbail cont:
7666e91bba0SGirish Moodalbail statep->sps_status = IPADM_SUCCESS;
7676e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", propval);
7686e91bba0SGirish Moodalbail }
7696e91bba0SGirish Moodalbail
7706e91bba0SGirish Moodalbail /*
7718c8556f9SYuri Pankov * Callback function for show-*prop subcommands.
7726e91bba0SGirish Moodalbail */
7736e91bba0SGirish Moodalbail static boolean_t
print_prop_cb(ofmt_arg_t * ofarg,char * buf,size_t bufsize)7746e91bba0SGirish Moodalbail print_prop_cb(ofmt_arg_t *ofarg, char *buf, size_t bufsize)
7756e91bba0SGirish Moodalbail {
7766e91bba0SGirish Moodalbail show_prop_state_t *statep = ofarg->ofmt_cbarg;
7776e91bba0SGirish Moodalbail const char *propname = statep->sps_pname;
7786e91bba0SGirish Moodalbail uint_t proto = statep->sps_proto;
7796e91bba0SGirish Moodalbail boolean_t cont = _B_TRUE;
7806e91bba0SGirish Moodalbail
7816e91bba0SGirish Moodalbail /*
7826e91bba0SGirish Moodalbail * Fail retrieving remaining fields, if you fail
7836e91bba0SGirish Moodalbail * to retrieve a field.
7846e91bba0SGirish Moodalbail */
7856e91bba0SGirish Moodalbail if (statep->sps_status != IPADM_SUCCESS)
7866e91bba0SGirish Moodalbail return (_B_FALSE);
7876e91bba0SGirish Moodalbail
7886e91bba0SGirish Moodalbail switch (ofarg->ofmt_id) {
7896e91bba0SGirish Moodalbail case IPADM_PROPFIELD_IFNAME:
7906e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", statep->sps_ifname);
7916e91bba0SGirish Moodalbail break;
7926e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PROTO:
7936e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", ipadm_proto2str(proto));
7946e91bba0SGirish Moodalbail break;
7956e91bba0SGirish Moodalbail case IPADM_PROPFIELD_ADDROBJ:
7966e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", statep->sps_aobjname);
7976e91bba0SGirish Moodalbail break;
7986e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PROPERTY:
7996e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", propname);
8006e91bba0SGirish Moodalbail break;
8016e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PERM:
8026e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_PERM, buf, bufsize);
8036e91bba0SGirish Moodalbail break;
8046e91bba0SGirish Moodalbail case IPADM_PROPFIELD_CURRENT:
8056e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_ACTIVE, buf, bufsize);
8066e91bba0SGirish Moodalbail break;
8076e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PERSISTENT:
8086e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_PERSIST, buf, bufsize);
8096e91bba0SGirish Moodalbail break;
8106e91bba0SGirish Moodalbail case IPADM_PROPFIELD_DEFAULT:
8116e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_DEFAULT, buf, bufsize);
8126e91bba0SGirish Moodalbail break;
8136e91bba0SGirish Moodalbail case IPADM_PROPFIELD_POSSIBLE:
8146e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_POSSIBLE, buf, bufsize);
8156e91bba0SGirish Moodalbail break;
8166e91bba0SGirish Moodalbail }
8176e91bba0SGirish Moodalbail if (statep->sps_status != IPADM_SUCCESS)
8186e91bba0SGirish Moodalbail cont = _B_FALSE;
8196e91bba0SGirish Moodalbail return (cont);
8206e91bba0SGirish Moodalbail }
8216e91bba0SGirish Moodalbail
8226e91bba0SGirish Moodalbail /*
8236e91bba0SGirish Moodalbail * Callback function called by the property walker (ipadm_walk_prop() or
8246e91bba0SGirish Moodalbail * ipadm_walk_proptbl()), for every matched property. This function in turn
8256e91bba0SGirish Moodalbail * calls ofmt_print() to print property information.
8266e91bba0SGirish Moodalbail */
8276e91bba0SGirish Moodalbail boolean_t
show_property(void * arg,const char * pname,uint_t proto)8286e91bba0SGirish Moodalbail show_property(void *arg, const char *pname, uint_t proto)
8296e91bba0SGirish Moodalbail {
8306e91bba0SGirish Moodalbail show_prop_state_t *statep = arg;
8316e91bba0SGirish Moodalbail
8326e91bba0SGirish Moodalbail statep->sps_pname = pname;
8336e91bba0SGirish Moodalbail statep->sps_proto = proto;
8346e91bba0SGirish Moodalbail statep->sps_status = IPADM_SUCCESS;
8356e91bba0SGirish Moodalbail ofmt_print(statep->sps_ofmt, arg);
8366e91bba0SGirish Moodalbail
8376e91bba0SGirish Moodalbail /*
8386e91bba0SGirish Moodalbail * if an object is not found or operation is not supported then
8396e91bba0SGirish Moodalbail * stop the walker.
8406e91bba0SGirish Moodalbail */
8416e91bba0SGirish Moodalbail if (statep->sps_status == IPADM_NOTFOUND ||
8426e91bba0SGirish Moodalbail statep->sps_status == IPADM_NOTSUP)
8436e91bba0SGirish Moodalbail return (_B_FALSE);
8446e91bba0SGirish Moodalbail return (_B_TRUE);
8456e91bba0SGirish Moodalbail }
8466e91bba0SGirish Moodalbail
8476e91bba0SGirish Moodalbail /*
8486e91bba0SGirish Moodalbail * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
849b31320a7SChris Fraire * for all the properties for the specified object, display relevant
850b31320a7SChris Fraire * information. Otherwise, for the selected property set, display relevant
8516e91bba0SGirish Moodalbail * information
8526e91bba0SGirish Moodalbail */
8536e91bba0SGirish Moodalbail static void
show_properties(void * arg,int prop_class)8546e91bba0SGirish Moodalbail show_properties(void *arg, int prop_class)
8556e91bba0SGirish Moodalbail {
8566e91bba0SGirish Moodalbail show_prop_state_t *statep = arg;
857467e811cSToomas Soome nvlist_t *nvl = statep->sps_proplist;
8586e91bba0SGirish Moodalbail uint_t proto = statep->sps_proto;
8596e91bba0SGirish Moodalbail nvpair_t *curr_nvp;
860467e811cSToomas Soome char *buf, *name;
8616e91bba0SGirish Moodalbail ipadm_status_t status;
8626e91bba0SGirish Moodalbail
8636e91bba0SGirish Moodalbail /* allocate sufficient buffer to hold a property value */
8646e91bba0SGirish Moodalbail if ((buf = malloc(MAXPROPVALLEN)) == NULL)
8656e91bba0SGirish Moodalbail die("insufficient memory");
8666e91bba0SGirish Moodalbail statep->sps_propval = buf;
8676e91bba0SGirish Moodalbail
8686e91bba0SGirish Moodalbail /* if no properties were specified, display all the properties */
8696e91bba0SGirish Moodalbail if (nvl == NULL) {
8706e91bba0SGirish Moodalbail (void) ipadm_walk_proptbl(proto, prop_class, show_property,
8716e91bba0SGirish Moodalbail statep);
8726e91bba0SGirish Moodalbail } else {
8736e91bba0SGirish Moodalbail for (curr_nvp = nvlist_next_nvpair(nvl, NULL); curr_nvp;
8746e91bba0SGirish Moodalbail curr_nvp = nvlist_next_nvpair(nvl, curr_nvp)) {
8756e91bba0SGirish Moodalbail name = nvpair_name(curr_nvp);
8766e91bba0SGirish Moodalbail status = ipadm_walk_prop(name, proto, prop_class,
8776e91bba0SGirish Moodalbail show_property, statep);
8786e91bba0SGirish Moodalbail if (status == IPADM_PROP_UNKNOWN)
8796e91bba0SGirish Moodalbail (void) show_property(statep, name, proto);
8806e91bba0SGirish Moodalbail }
8816e91bba0SGirish Moodalbail }
8826e91bba0SGirish Moodalbail
8836e91bba0SGirish Moodalbail free(buf);
8846e91bba0SGirish Moodalbail }
8856e91bba0SGirish Moodalbail
8866e91bba0SGirish Moodalbail /*
8876e91bba0SGirish Moodalbail * Display information for all or specific interface properties, either for a
8886e91bba0SGirish Moodalbail * given interface or for all the interfaces in the system.
8896e91bba0SGirish Moodalbail */
8906e91bba0SGirish Moodalbail static void
do_show_ifprop(int argc,char ** argv,const char * use)8916e91bba0SGirish Moodalbail do_show_ifprop(int argc, char **argv, const char *use)
8926e91bba0SGirish Moodalbail {
893467e811cSToomas Soome int option;
894467e811cSToomas Soome nvlist_t *proplist = NULL;
8956e91bba0SGirish Moodalbail char *fields_str = NULL;
896467e811cSToomas Soome char *ifname;
8976e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
8986e91bba0SGirish Moodalbail ofmt_status_t oferr;
8996e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
9006e91bba0SGirish Moodalbail uint_t proto;
9016e91bba0SGirish Moodalbail boolean_t m_arg = _B_FALSE;
9026e91bba0SGirish Moodalbail char *protostr;
903a73be61aSHans Rosenfeld ipadm_if_info_t *ifinfo, *ifp;
9046e91bba0SGirish Moodalbail ipadm_status_t status;
9056e91bba0SGirish Moodalbail show_prop_state_t state;
9066e91bba0SGirish Moodalbail
907467e811cSToomas Soome protostr = "ip";
9086e91bba0SGirish Moodalbail opterr = 0;
9096e91bba0SGirish Moodalbail bzero(&state, sizeof (state));
9106e91bba0SGirish Moodalbail state.sps_propval = NULL;
9116e91bba0SGirish Moodalbail state.sps_parsable = _B_FALSE;
9126e91bba0SGirish Moodalbail state.sps_ifprop = _B_TRUE;
9136e91bba0SGirish Moodalbail state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
9146e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:m:co:",
9156e91bba0SGirish Moodalbail show_ifprop_longopts, NULL)) != -1) {
9166e91bba0SGirish Moodalbail switch (option) {
9176e91bba0SGirish Moodalbail case 'p':
9186e91bba0SGirish Moodalbail if (ipadm_str2nvlist(optarg, &proplist,
9196e91bba0SGirish Moodalbail IPADM_NORVAL) != 0)
9206e91bba0SGirish Moodalbail die("invalid interface properties specified");
9216e91bba0SGirish Moodalbail break;
9226e91bba0SGirish Moodalbail case 'c':
9236e91bba0SGirish Moodalbail state.sps_parsable = _B_TRUE;
9246e91bba0SGirish Moodalbail break;
9256e91bba0SGirish Moodalbail case 'o':
9266e91bba0SGirish Moodalbail fields_str = optarg;
9276e91bba0SGirish Moodalbail break;
9286e91bba0SGirish Moodalbail case 'm':
9296e91bba0SGirish Moodalbail if (m_arg)
9306e91bba0SGirish Moodalbail die("cannot specify more than one -m");
9316e91bba0SGirish Moodalbail m_arg = _B_TRUE;
9326e91bba0SGirish Moodalbail protostr = optarg;
9336e91bba0SGirish Moodalbail break;
9346e91bba0SGirish Moodalbail default:
9356e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
9366e91bba0SGirish Moodalbail break;
9376e91bba0SGirish Moodalbail }
9386e91bba0SGirish Moodalbail }
9396e91bba0SGirish Moodalbail
9406e91bba0SGirish Moodalbail if (optind == argc - 1)
9416e91bba0SGirish Moodalbail ifname = argv[optind];
9426e91bba0SGirish Moodalbail else if (optind != argc)
9436e91bba0SGirish Moodalbail die("Usage: %s", use);
9446e91bba0SGirish Moodalbail else
9456e91bba0SGirish Moodalbail ifname = NULL;
9466e91bba0SGirish Moodalbail
9476e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
9486e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
9496e91bba0SGirish Moodalbail
9506e91bba0SGirish Moodalbail state.sps_proto = proto;
9516e91bba0SGirish Moodalbail state.sps_proplist = proplist;
9526e91bba0SGirish Moodalbail
9536e91bba0SGirish Moodalbail if (state.sps_parsable)
9546e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
9556e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
956b2f26520SBryan Cantrill ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
9576e91bba0SGirish Moodalbail state.sps_ofmt = ofmt;
9586e91bba0SGirish Moodalbail
9596e91bba0SGirish Moodalbail /* retrieve interface(s) and print the properties */
9606e91bba0SGirish Moodalbail status = ipadm_if_info(iph, ifname, &ifinfo, 0, LIFC_DEFAULT);
9616e91bba0SGirish Moodalbail if (ifname != NULL && status == IPADM_ENXIO)
9626e91bba0SGirish Moodalbail die("no such object '%s': %s", ifname,
9636e91bba0SGirish Moodalbail ipadm_status2str(status));
9646e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
9656e91bba0SGirish Moodalbail die("Error retrieving interface(s): %s",
9666e91bba0SGirish Moodalbail ipadm_status2str(status));
967a73be61aSHans Rosenfeld for (ifp = ifinfo; ifp != NULL; ifp = ifp->ifi_next) {
968a73be61aSHans Rosenfeld (void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);
9696e91bba0SGirish Moodalbail state.sps_proto = proto;
9706e91bba0SGirish Moodalbail show_properties(&state, IPADMPROP_CLASS_IF);
9716e91bba0SGirish Moodalbail }
9726e91bba0SGirish Moodalbail if (ifinfo)
9736e91bba0SGirish Moodalbail ipadm_free_if_info(ifinfo);
9746e91bba0SGirish Moodalbail
9756e91bba0SGirish Moodalbail nvlist_free(proplist);
9766e91bba0SGirish Moodalbail ofmt_close(ofmt);
9776e91bba0SGirish Moodalbail
9786e91bba0SGirish Moodalbail if (state.sps_retstatus != IPADM_SUCCESS) {
9796e91bba0SGirish Moodalbail ipadm_close(iph);
9806e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
9816e91bba0SGirish Moodalbail }
9826e91bba0SGirish Moodalbail }
9836e91bba0SGirish Moodalbail
9846e91bba0SGirish Moodalbail /*
9856e91bba0SGirish Moodalbail * set/reset the interface property for a given interface.
9866e91bba0SGirish Moodalbail */
9876e91bba0SGirish Moodalbail static void
set_ifprop(int argc,char ** argv,boolean_t reset,const char * use)9886e91bba0SGirish Moodalbail set_ifprop(int argc, char **argv, boolean_t reset, const char *use)
9896e91bba0SGirish Moodalbail {
990467e811cSToomas Soome int option;
991467e811cSToomas Soome ipadm_status_t status = IPADM_SUCCESS;
992467e811cSToomas Soome boolean_t p_arg = _B_FALSE;
9936e91bba0SGirish Moodalbail boolean_t m_arg = _B_FALSE;
994467e811cSToomas Soome char *ifname, *nv, *protostr;
9956e91bba0SGirish Moodalbail char *prop_name, *prop_val;
9966e91bba0SGirish Moodalbail uint_t flags = IPADM_OPT_PERSIST;
9976e91bba0SGirish Moodalbail uint_t proto;
9986e91bba0SGirish Moodalbail
999467e811cSToomas Soome nv = NULL;
1000467e811cSToomas Soome protostr = NULL;
10016e91bba0SGirish Moodalbail opterr = 0;
10026e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":m:p:t",
10036e91bba0SGirish Moodalbail set_ifprop_longopts, NULL)) != -1) {
10046e91bba0SGirish Moodalbail switch (option) {
10056e91bba0SGirish Moodalbail case 'p':
10066e91bba0SGirish Moodalbail if (p_arg)
10076e91bba0SGirish Moodalbail die("-p must be specified once only");
10086e91bba0SGirish Moodalbail p_arg = _B_TRUE;
10096e91bba0SGirish Moodalbail
10106e91bba0SGirish Moodalbail ipadm_check_propstr(optarg, reset, use);
10116e91bba0SGirish Moodalbail nv = optarg;
10126e91bba0SGirish Moodalbail break;
10136e91bba0SGirish Moodalbail case 'm':
10146e91bba0SGirish Moodalbail if (m_arg)
10156e91bba0SGirish Moodalbail die("-m must be specified once only");
10166e91bba0SGirish Moodalbail m_arg = _B_TRUE;
10176e91bba0SGirish Moodalbail protostr = optarg;
10186e91bba0SGirish Moodalbail break;
10196e91bba0SGirish Moodalbail case 't':
10206e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
10216e91bba0SGirish Moodalbail break;
10226e91bba0SGirish Moodalbail default:
10236e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
10246e91bba0SGirish Moodalbail }
10256e91bba0SGirish Moodalbail }
10266e91bba0SGirish Moodalbail
10276e91bba0SGirish Moodalbail if (!m_arg || !p_arg || optind != argc - 1)
10286e91bba0SGirish Moodalbail die("Usage: %s", use);
10296e91bba0SGirish Moodalbail
10306e91bba0SGirish Moodalbail ifname = argv[optind];
10316e91bba0SGirish Moodalbail
10326e91bba0SGirish Moodalbail prop_name = nv;
10336e91bba0SGirish Moodalbail prop_val = strchr(nv, '=');
10346e91bba0SGirish Moodalbail if (prop_val != NULL)
10356e91bba0SGirish Moodalbail *prop_val++ = '\0';
10366e91bba0SGirish Moodalbail
10376e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
10386e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
10396e91bba0SGirish Moodalbail
10406e91bba0SGirish Moodalbail if (reset)
10416e91bba0SGirish Moodalbail flags |= IPADM_OPT_DEFAULT;
10426e91bba0SGirish Moodalbail else
10436e91bba0SGirish Moodalbail flags |= IPADM_OPT_ACTIVE;
10446e91bba0SGirish Moodalbail status = ipadm_set_ifprop(iph, ifname, prop_name, prop_val, proto,
10456e91bba0SGirish Moodalbail flags);
10466e91bba0SGirish Moodalbail
10476e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
10486e91bba0SGirish Moodalbail if (reset)
10496e91bba0SGirish Moodalbail die("reset-ifprop: %s: %s",
10506e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
10516e91bba0SGirish Moodalbail else
10526e91bba0SGirish Moodalbail die("set-ifprop: %s: %s",
10536e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
10546e91bba0SGirish Moodalbail }
10556e91bba0SGirish Moodalbail }
10566e91bba0SGirish Moodalbail
10576e91bba0SGirish Moodalbail static void
do_set_ifprop(int argc,char ** argv,const char * use)10586e91bba0SGirish Moodalbail do_set_ifprop(int argc, char **argv, const char *use)
10596e91bba0SGirish Moodalbail {
10606e91bba0SGirish Moodalbail set_ifprop(argc, argv, _B_FALSE, use);
10616e91bba0SGirish Moodalbail }
10626e91bba0SGirish Moodalbail
10636e91bba0SGirish Moodalbail static void
do_reset_ifprop(int argc,char ** argv,const char * use)10646e91bba0SGirish Moodalbail do_reset_ifprop(int argc, char **argv, const char *use)
10656e91bba0SGirish Moodalbail {
10666e91bba0SGirish Moodalbail set_ifprop(argc, argv, _B_TRUE, use);
10676e91bba0SGirish Moodalbail }
10686e91bba0SGirish Moodalbail
10696e91bba0SGirish Moodalbail /*
10706e91bba0SGirish Moodalbail * Display information for all or specific protocol properties, either for a
10716e91bba0SGirish Moodalbail * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
10726e91bba0SGirish Moodalbail */
10736e91bba0SGirish Moodalbail static void
do_show_prop(int argc,char ** argv,const char * use)10746e91bba0SGirish Moodalbail do_show_prop(int argc, char **argv, const char *use)
10756e91bba0SGirish Moodalbail {
1076*ef150c2bSRichard Lowe int option;
1077467e811cSToomas Soome nvlist_t *proplist = NULL;
10786e91bba0SGirish Moodalbail char *fields_str = NULL;
1079467e811cSToomas Soome char *protostr;
1080467e811cSToomas Soome show_prop_state_t state;
10816e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
10826e91bba0SGirish Moodalbail ofmt_status_t oferr;
10836e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
10846e91bba0SGirish Moodalbail uint_t proto;
10856e91bba0SGirish Moodalbail boolean_t p_arg = _B_FALSE;
10866e91bba0SGirish Moodalbail
10876e91bba0SGirish Moodalbail opterr = 0;
10886e91bba0SGirish Moodalbail bzero(&state, sizeof (state));
10896e91bba0SGirish Moodalbail state.sps_propval = NULL;
10906e91bba0SGirish Moodalbail state.sps_parsable = _B_FALSE;
10916e91bba0SGirish Moodalbail state.sps_modprop = _B_TRUE;
10926e91bba0SGirish Moodalbail state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
10936e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:co:", show_prop_longopts,
10946e91bba0SGirish Moodalbail NULL)) != -1) {
10956e91bba0SGirish Moodalbail switch (option) {
10966e91bba0SGirish Moodalbail case 'p':
10976e91bba0SGirish Moodalbail if (p_arg)
10986e91bba0SGirish Moodalbail die("-p must be specified once only");
10996e91bba0SGirish Moodalbail p_arg = _B_TRUE;
11006e91bba0SGirish Moodalbail if (ipadm_str2nvlist(optarg, &proplist,
11016e91bba0SGirish Moodalbail IPADM_NORVAL) != 0)
11026e91bba0SGirish Moodalbail die("invalid protocol properties specified");
11036e91bba0SGirish Moodalbail break;
11046e91bba0SGirish Moodalbail case 'c':
11056e91bba0SGirish Moodalbail state.sps_parsable = _B_TRUE;
11066e91bba0SGirish Moodalbail break;
11076e91bba0SGirish Moodalbail case 'o':
11086e91bba0SGirish Moodalbail fields_str = optarg;
11096e91bba0SGirish Moodalbail break;
11106e91bba0SGirish Moodalbail default:
11116e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
11126e91bba0SGirish Moodalbail break;
11136e91bba0SGirish Moodalbail }
11146e91bba0SGirish Moodalbail }
11156e91bba0SGirish Moodalbail if (optind == argc - 1) {
11166e91bba0SGirish Moodalbail protostr = argv[optind];
11176e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
11186e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
11196e91bba0SGirish Moodalbail state.sps_proto = proto;
11206e91bba0SGirish Moodalbail } else if (optind != argc) {
11216e91bba0SGirish Moodalbail die("Usage: %s", use);
11226e91bba0SGirish Moodalbail } else {
11236e91bba0SGirish Moodalbail if (p_arg)
11246e91bba0SGirish Moodalbail die("protocol must be specified when "
11256e91bba0SGirish Moodalbail "property name is used");
11266e91bba0SGirish Moodalbail state.sps_proto = MOD_PROTO_NONE;
11276e91bba0SGirish Moodalbail }
11286e91bba0SGirish Moodalbail
11296e91bba0SGirish Moodalbail state.sps_proplist = proplist;
11306e91bba0SGirish Moodalbail
11316e91bba0SGirish Moodalbail if (state.sps_parsable)
11326e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
11336e91bba0SGirish Moodalbail else
11346e91bba0SGirish Moodalbail ofmtflags |= OFMT_WRAP;
11356e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
1136b2f26520SBryan Cantrill ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
11376e91bba0SGirish Moodalbail state.sps_ofmt = ofmt;
11386e91bba0SGirish Moodalbail
11396e91bba0SGirish Moodalbail /* handles all the errors */
11406e91bba0SGirish Moodalbail show_properties(&state, IPADMPROP_CLASS_MODULE);
11416e91bba0SGirish Moodalbail
11426e91bba0SGirish Moodalbail nvlist_free(proplist);
11436e91bba0SGirish Moodalbail ofmt_close(ofmt);
11446e91bba0SGirish Moodalbail
11456e91bba0SGirish Moodalbail if (state.sps_retstatus != IPADM_SUCCESS) {
11466e91bba0SGirish Moodalbail ipadm_close(iph);
11476e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
11486e91bba0SGirish Moodalbail }
11496e91bba0SGirish Moodalbail }
11506e91bba0SGirish Moodalbail
11516e91bba0SGirish Moodalbail /*
11526e91bba0SGirish Moodalbail * Checks to see if there are any modifiers, + or -. If there are modifiers
11536e91bba0SGirish Moodalbail * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
11546e91bba0SGirish Moodalbail */
11556e91bba0SGirish Moodalbail static void
parse_modifiers(const char * pstr,uint_t * flags,const char * use)11568b88711aSGirish Moodalbail parse_modifiers(const char *pstr, uint_t *flags, const char *use)
11576e91bba0SGirish Moodalbail {
11586e91bba0SGirish Moodalbail char *p;
11596e91bba0SGirish Moodalbail
11608b88711aSGirish Moodalbail if ((p = strchr(pstr, '=')) == NULL)
11618b88711aSGirish Moodalbail return;
11626e91bba0SGirish Moodalbail
11638b88711aSGirish Moodalbail if (p == pstr)
11648b88711aSGirish Moodalbail die("Invalid prop=val specified\n%s", use);
11656e91bba0SGirish Moodalbail
11668b88711aSGirish Moodalbail --p;
11678b88711aSGirish Moodalbail if (*p == '+')
11686e91bba0SGirish Moodalbail *flags |= IPADM_OPT_APPEND;
11698b88711aSGirish Moodalbail else if (*p == '-')
11706e91bba0SGirish Moodalbail *flags |= IPADM_OPT_REMOVE;
11716e91bba0SGirish Moodalbail }
11726e91bba0SGirish Moodalbail
11736e91bba0SGirish Moodalbail /*
11746e91bba0SGirish Moodalbail * set/reset the protocol property for a given protocol.
11756e91bba0SGirish Moodalbail */
11766e91bba0SGirish Moodalbail static void
set_prop(int argc,char ** argv,boolean_t reset,const char * use)11776e91bba0SGirish Moodalbail set_prop(int argc, char **argv, boolean_t reset, const char *use)
11786e91bba0SGirish Moodalbail {
1179467e811cSToomas Soome int option;
1180467e811cSToomas Soome ipadm_status_t status = IPADM_SUCCESS;
1181467e811cSToomas Soome char *protostr, *nv, *prop_name, *prop_val;
1182467e811cSToomas Soome boolean_t p_arg = _B_FALSE;
1183467e811cSToomas Soome uint_t proto;
11846e91bba0SGirish Moodalbail uint_t flags = IPADM_OPT_PERSIST;
11856e91bba0SGirish Moodalbail
1186467e811cSToomas Soome nv = NULL;
11876e91bba0SGirish Moodalbail opterr = 0;
11886e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:t", set_prop_longopts,
11896e91bba0SGirish Moodalbail NULL)) != -1) {
11906e91bba0SGirish Moodalbail switch (option) {
11916e91bba0SGirish Moodalbail case 'p':
11926e91bba0SGirish Moodalbail if (p_arg)
11936e91bba0SGirish Moodalbail die("-p must be specified once only");
11946e91bba0SGirish Moodalbail p_arg = _B_TRUE;
11956e91bba0SGirish Moodalbail
11966e91bba0SGirish Moodalbail ipadm_check_propstr(optarg, reset, use);
11976e91bba0SGirish Moodalbail nv = optarg;
11986e91bba0SGirish Moodalbail break;
11996e91bba0SGirish Moodalbail case 't':
12006e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
12016e91bba0SGirish Moodalbail break;
12026e91bba0SGirish Moodalbail default:
12036e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
12046e91bba0SGirish Moodalbail }
12056e91bba0SGirish Moodalbail }
12066e91bba0SGirish Moodalbail
12076e91bba0SGirish Moodalbail if (!p_arg || optind != argc - 1)
12086e91bba0SGirish Moodalbail die("Usage: %s", use);
12096e91bba0SGirish Moodalbail
12106e91bba0SGirish Moodalbail parse_modifiers(nv, &flags, use);
12116e91bba0SGirish Moodalbail prop_name = nv;
12126e91bba0SGirish Moodalbail prop_val = strchr(nv, '=');
12136e91bba0SGirish Moodalbail if (prop_val != NULL) {
12146e91bba0SGirish Moodalbail if (flags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))
12156e91bba0SGirish Moodalbail *(prop_val - 1) = '\0';
12166e91bba0SGirish Moodalbail *prop_val++ = '\0';
12176e91bba0SGirish Moodalbail }
12186e91bba0SGirish Moodalbail protostr = argv[optind];
12196e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
12206e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
12216e91bba0SGirish Moodalbail
12226e91bba0SGirish Moodalbail if (reset)
12236e91bba0SGirish Moodalbail flags |= IPADM_OPT_DEFAULT;
12246e91bba0SGirish Moodalbail else
12256e91bba0SGirish Moodalbail flags |= IPADM_OPT_ACTIVE;
12266e91bba0SGirish Moodalbail status = ipadm_set_prop(iph, prop_name, prop_val, proto, flags);
1227467e811cSToomas Soome
12286e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
12296e91bba0SGirish Moodalbail if (reset)
12306e91bba0SGirish Moodalbail die("reset-prop: %s: %s",
12316e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
12326e91bba0SGirish Moodalbail else
12336e91bba0SGirish Moodalbail die("set-prop: %s: %s",
12346e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
12356e91bba0SGirish Moodalbail }
12366e91bba0SGirish Moodalbail }
12376e91bba0SGirish Moodalbail
12386e91bba0SGirish Moodalbail static void
do_set_prop(int argc,char ** argv,const char * use)12396e91bba0SGirish Moodalbail do_set_prop(int argc, char **argv, const char *use)
12406e91bba0SGirish Moodalbail {
12416e91bba0SGirish Moodalbail set_prop(argc, argv, _B_FALSE, use);
12426e91bba0SGirish Moodalbail }
12436e91bba0SGirish Moodalbail
12446e91bba0SGirish Moodalbail static void
do_reset_prop(int argc,char ** argv,const char * use)12456e91bba0SGirish Moodalbail do_reset_prop(int argc, char **argv, const char *use)
12466e91bba0SGirish Moodalbail {
12476e91bba0SGirish Moodalbail set_prop(argc, argv, _B_TRUE, use);
12486e91bba0SGirish Moodalbail }
12496e91bba0SGirish Moodalbail
12506e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
12516e91bba0SGirish Moodalbail static void
warn(const char * format,...)12526e91bba0SGirish Moodalbail warn(const char *format, ...)
12536e91bba0SGirish Moodalbail {
12546e91bba0SGirish Moodalbail va_list alist;
12556e91bba0SGirish Moodalbail
12566e91bba0SGirish Moodalbail format = gettext(format);
12576e91bba0SGirish Moodalbail (void) fprintf(stderr, gettext("%s: warning: "), progname);
12586e91bba0SGirish Moodalbail
12596e91bba0SGirish Moodalbail va_start(alist, format);
12606e91bba0SGirish Moodalbail (void) vfprintf(stderr, format, alist);
12616e91bba0SGirish Moodalbail va_end(alist);
12626e91bba0SGirish Moodalbail
12636e91bba0SGirish Moodalbail (void) fprintf(stderr, "\n");
12646e91bba0SGirish Moodalbail }
12656e91bba0SGirish Moodalbail
12666e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
12676e91bba0SGirish Moodalbail static void
die(const char * format,...)12686e91bba0SGirish Moodalbail die(const char *format, ...)
12696e91bba0SGirish Moodalbail {
12706e91bba0SGirish Moodalbail va_list alist;
12716e91bba0SGirish Moodalbail
1272a73be61aSHans Rosenfeld if (format != NULL) {
1273a73be61aSHans Rosenfeld format = gettext(format);
1274a73be61aSHans Rosenfeld (void) fprintf(stderr, "%s: ", progname);
12756e91bba0SGirish Moodalbail
1276a73be61aSHans Rosenfeld va_start(alist, format);
1277a73be61aSHans Rosenfeld (void) vfprintf(stderr, format, alist);
1278a73be61aSHans Rosenfeld va_end(alist);
12796e91bba0SGirish Moodalbail
1280a73be61aSHans Rosenfeld (void) putchar('\n');
1281a73be61aSHans Rosenfeld }
12826e91bba0SGirish Moodalbail
12836e91bba0SGirish Moodalbail ipadm_destroy_addrobj(ipaddr);
12846e91bba0SGirish Moodalbail ipadm_close(iph);
12856e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
12866e91bba0SGirish Moodalbail }
12876e91bba0SGirish Moodalbail
12886e91bba0SGirish Moodalbail static void
die_opterr(int opt,int opterr,const char * usage)12896e91bba0SGirish Moodalbail die_opterr(int opt, int opterr, const char *usage)
12906e91bba0SGirish Moodalbail {
12916e91bba0SGirish Moodalbail switch (opterr) {
12926e91bba0SGirish Moodalbail case ':':
12936e91bba0SGirish Moodalbail die("option '-%c' requires a value\nusage: %s", opt,
12946e91bba0SGirish Moodalbail gettext(usage));
12956e91bba0SGirish Moodalbail break;
12966e91bba0SGirish Moodalbail case '?':
12976e91bba0SGirish Moodalbail default:
12986e91bba0SGirish Moodalbail die("unrecognized option '-%c'\nusage: %s", opt,
12996e91bba0SGirish Moodalbail gettext(usage));
13006e91bba0SGirish Moodalbail break;
13016e91bba0SGirish Moodalbail }
13026e91bba0SGirish Moodalbail }
13036e91bba0SGirish Moodalbail
13046e91bba0SGirish Moodalbail /* PRINTFLIKE2 */
13056e91bba0SGirish Moodalbail static void
warn_ipadmerr(ipadm_status_t err,const char * format,...)13066e91bba0SGirish Moodalbail warn_ipadmerr(ipadm_status_t err, const char *format, ...)
13076e91bba0SGirish Moodalbail {
13086e91bba0SGirish Moodalbail va_list alist;
13096e91bba0SGirish Moodalbail
13106e91bba0SGirish Moodalbail format = gettext(format);
13116e91bba0SGirish Moodalbail (void) fprintf(stderr, gettext("%s: warning: "), progname);
13126e91bba0SGirish Moodalbail
13136e91bba0SGirish Moodalbail va_start(alist, format);
13146e91bba0SGirish Moodalbail (void) vfprintf(stderr, format, alist);
13156e91bba0SGirish Moodalbail va_end(alist);
13166e91bba0SGirish Moodalbail
13176e91bba0SGirish Moodalbail (void) fprintf(stderr, "%s\n", ipadm_status2str(err));
13186e91bba0SGirish Moodalbail }
13196e91bba0SGirish Moodalbail
13206e91bba0SGirish Moodalbail static void
process_static_addrargs(const char * use,char * addrarg,const char * aobjname)13216e91bba0SGirish Moodalbail process_static_addrargs(const char *use, char *addrarg, const char *aobjname)
13226e91bba0SGirish Moodalbail {
13236e91bba0SGirish Moodalbail int option;
13246e91bba0SGirish Moodalbail char *val;
13256e91bba0SGirish Moodalbail char *laddr = NULL;
13266e91bba0SGirish Moodalbail char *raddr = NULL;
13276e91bba0SGirish Moodalbail char *save_input_arg = addrarg;
13286e91bba0SGirish Moodalbail boolean_t found_mismatch = _B_FALSE;
13296e91bba0SGirish Moodalbail ipadm_status_t status;
13306e91bba0SGirish Moodalbail enum { A_LOCAL, A_REMOTE };
13316e91bba0SGirish Moodalbail static char *addr_optstr[] = {
13326e91bba0SGirish Moodalbail "local",
13336e91bba0SGirish Moodalbail "remote",
13346e91bba0SGirish Moodalbail NULL,
13356e91bba0SGirish Moodalbail };
13366e91bba0SGirish Moodalbail
13376e91bba0SGirish Moodalbail while (*addrarg != '\0') {
13386e91bba0SGirish Moodalbail option = getsubopt(&addrarg, addr_optstr, &val);
13396e91bba0SGirish Moodalbail switch (option) {
13406e91bba0SGirish Moodalbail case A_LOCAL:
13416e91bba0SGirish Moodalbail if (laddr != NULL)
13426e91bba0SGirish Moodalbail die("Multiple local addresses provided");
13436e91bba0SGirish Moodalbail laddr = val;
13446e91bba0SGirish Moodalbail break;
13456e91bba0SGirish Moodalbail case A_REMOTE:
13466e91bba0SGirish Moodalbail if (raddr != NULL)
13476e91bba0SGirish Moodalbail die("Multiple remote addresses provided");
13486e91bba0SGirish Moodalbail raddr = val;
13496e91bba0SGirish Moodalbail break;
13506e91bba0SGirish Moodalbail default:
13516e91bba0SGirish Moodalbail if (found_mismatch)
13526e91bba0SGirish Moodalbail die("Invalid address provided\nusage: %s", use);
13536e91bba0SGirish Moodalbail found_mismatch = _B_TRUE;
13546e91bba0SGirish Moodalbail break;
13556e91bba0SGirish Moodalbail }
13566e91bba0SGirish Moodalbail }
13576e91bba0SGirish Moodalbail if (raddr != NULL && laddr == NULL)
13586e91bba0SGirish Moodalbail die("Missing local address\nusage: %s", use);
13596e91bba0SGirish Moodalbail
13606e91bba0SGirish Moodalbail /* If only one address is provided, it is assumed a local address. */
13616e91bba0SGirish Moodalbail if (laddr == NULL) {
13626e91bba0SGirish Moodalbail if (found_mismatch)
13636e91bba0SGirish Moodalbail laddr = save_input_arg;
13646e91bba0SGirish Moodalbail else
13656e91bba0SGirish Moodalbail die("Missing local address\nusage: %s", use);
13666e91bba0SGirish Moodalbail }
13676e91bba0SGirish Moodalbail
13686e91bba0SGirish Moodalbail /* Initialize the addrobj for static addresses. */
13696e91bba0SGirish Moodalbail status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname, &ipaddr);
13706e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
13716e91bba0SGirish Moodalbail die("Error in creating address object: %s",
13726e91bba0SGirish Moodalbail ipadm_status2str(status));
13736e91bba0SGirish Moodalbail }
13746e91bba0SGirish Moodalbail
13756e91bba0SGirish Moodalbail /* Set the local and remote addresses */
13766e91bba0SGirish Moodalbail status = ipadm_set_addr(ipaddr, laddr, AF_UNSPEC);
13776e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
13786e91bba0SGirish Moodalbail die("Error in setting local address: %s",
13796e91bba0SGirish Moodalbail ipadm_status2str(status));
13806e91bba0SGirish Moodalbail }
13816e91bba0SGirish Moodalbail if (raddr != NULL) {
13826e91bba0SGirish Moodalbail status = ipadm_set_dst_addr(ipaddr, raddr, AF_UNSPEC);
13836e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
13846e91bba0SGirish Moodalbail die("Error in setting remote address: %s",
13856e91bba0SGirish Moodalbail ipadm_status2str(status));
13866e91bba0SGirish Moodalbail }
13876e91bba0SGirish Moodalbail }
13886e91bba0SGirish Moodalbail }
13896e91bba0SGirish Moodalbail
13906e91bba0SGirish Moodalbail static void
process_addrconf_addrargs(const char * use,char * addrarg)13916e91bba0SGirish Moodalbail process_addrconf_addrargs(const char *use, char *addrarg)
13926e91bba0SGirish Moodalbail {
13936e91bba0SGirish Moodalbail int option;
13946e91bba0SGirish Moodalbail char *val;
13956e91bba0SGirish Moodalbail enum { P_STATELESS, P_STATEFUL };
13966e91bba0SGirish Moodalbail static char *addr_optstr[] = {
13976e91bba0SGirish Moodalbail "stateless",
13986e91bba0SGirish Moodalbail "stateful",
13996e91bba0SGirish Moodalbail NULL,
14006e91bba0SGirish Moodalbail };
1401467e811cSToomas Soome boolean_t stateless = _B_FALSE;
14026e91bba0SGirish Moodalbail boolean_t stateless_arg = _B_FALSE;
1403467e811cSToomas Soome boolean_t stateful = _B_FALSE;
14046e91bba0SGirish Moodalbail boolean_t stateful_arg = _B_FALSE;
14056e91bba0SGirish Moodalbail ipadm_status_t status;
14066e91bba0SGirish Moodalbail
14076e91bba0SGirish Moodalbail while (*addrarg != '\0') {
14086e91bba0SGirish Moodalbail option = getsubopt(&addrarg, addr_optstr, &val);
14096e91bba0SGirish Moodalbail switch (option) {
14106e91bba0SGirish Moodalbail case P_STATELESS:
14116e91bba0SGirish Moodalbail if (stateless_arg)
14126e91bba0SGirish Moodalbail die("Duplicate option");
14137bc87895SYuri Pankov if (val == NULL)
14147bc87895SYuri Pankov die("Invalid argument");
14156e91bba0SGirish Moodalbail if (strcmp(val, "yes") == 0)
14166e91bba0SGirish Moodalbail stateless = _B_TRUE;
14176e91bba0SGirish Moodalbail else if (strcmp(val, "no") == 0)
14186e91bba0SGirish Moodalbail stateless = _B_FALSE;
14196e91bba0SGirish Moodalbail else
14206e91bba0SGirish Moodalbail die("Invalid argument");
14216e91bba0SGirish Moodalbail stateless_arg = _B_TRUE;
14226e91bba0SGirish Moodalbail break;
14236e91bba0SGirish Moodalbail case P_STATEFUL:
14246e91bba0SGirish Moodalbail if (stateful_arg)
14256e91bba0SGirish Moodalbail die("Duplicate option");
14267bc87895SYuri Pankov if (val == NULL)
14277bc87895SYuri Pankov die("Invalid argument");
14286e91bba0SGirish Moodalbail if (strcmp(val, "yes") == 0)
14296e91bba0SGirish Moodalbail stateful = _B_TRUE;
14306e91bba0SGirish Moodalbail else if (strcmp(val, "no") == 0)
14316e91bba0SGirish Moodalbail stateful = _B_FALSE;
14326e91bba0SGirish Moodalbail else
14336e91bba0SGirish Moodalbail die("Invalid argument");
14346e91bba0SGirish Moodalbail stateful_arg = _B_TRUE;
14356e91bba0SGirish Moodalbail break;
14366e91bba0SGirish Moodalbail default:
14376e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
14386e91bba0SGirish Moodalbail }
14396e91bba0SGirish Moodalbail }
14406e91bba0SGirish Moodalbail
14416e91bba0SGirish Moodalbail if (!stateless_arg && !stateful_arg)
14426e91bba0SGirish Moodalbail die("Invalid arguments for option -p");
14436e91bba0SGirish Moodalbail
14446e91bba0SGirish Moodalbail /* Set the addrobj fields for addrconf */
14456e91bba0SGirish Moodalbail if (stateless_arg) {
14466e91bba0SGirish Moodalbail status = ipadm_set_stateless(ipaddr, stateless);
14476e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
14486e91bba0SGirish Moodalbail die("Error in setting stateless option: %s",
14496e91bba0SGirish Moodalbail ipadm_status2str(status));
14506e91bba0SGirish Moodalbail }
14516e91bba0SGirish Moodalbail }
14526e91bba0SGirish Moodalbail if (stateful_arg) {
14536e91bba0SGirish Moodalbail status = ipadm_set_stateful(ipaddr, stateful);
14546e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
14556e91bba0SGirish Moodalbail die("Error in setting stateful option: %s",
14566e91bba0SGirish Moodalbail ipadm_status2str(status));
14576e91bba0SGirish Moodalbail }
14586e91bba0SGirish Moodalbail }
14596e91bba0SGirish Moodalbail }
14606e91bba0SGirish Moodalbail
14616e91bba0SGirish Moodalbail /*
14626e91bba0SGirish Moodalbail * Creates static, dhcp or addrconf addresses and associates the created
14636e91bba0SGirish Moodalbail * addresses with the specified address object name.
14646e91bba0SGirish Moodalbail */
14656e91bba0SGirish Moodalbail static void
do_create_addr(int argc,char * argv[],const char * use)14666e91bba0SGirish Moodalbail do_create_addr(int argc, char *argv[], const char *use)
14676e91bba0SGirish Moodalbail {
14686e91bba0SGirish Moodalbail ipadm_status_t status;
14696e91bba0SGirish Moodalbail int option;
14706e91bba0SGirish Moodalbail uint32_t flags =
1471f6da83d4SAnurag S. Maskey IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
14726e91bba0SGirish Moodalbail char *cp;
14736e91bba0SGirish Moodalbail char *atype = NULL;
14746e91bba0SGirish Moodalbail char *static_arg = NULL;
14756e91bba0SGirish Moodalbail char *addrconf_arg = NULL;
14766e91bba0SGirish Moodalbail char *interface_id = NULL;
14776e91bba0SGirish Moodalbail char *wait = NULL;
1478b31320a7SChris Fraire char *reqhost = NULL;
14796e91bba0SGirish Moodalbail boolean_t s_opt = _B_FALSE; /* static addr options */
14806e91bba0SGirish Moodalbail boolean_t auto_opt = _B_FALSE; /* Addrconf options */
14816e91bba0SGirish Moodalbail boolean_t dhcp_opt = _B_FALSE; /* dhcp options */
1482b31320a7SChris Fraire boolean_t primary_opt = _B_FALSE; /* dhcp primary option */
14836e91bba0SGirish Moodalbail
14846e91bba0SGirish Moodalbail opterr = 0;
1485b31320a7SChris Fraire while ((option = getopt_long(argc, argv, ":1T:a:dh:i:p:w:t",
14866e91bba0SGirish Moodalbail addr_longopts, NULL)) != -1) {
14876e91bba0SGirish Moodalbail switch (option) {
1488b31320a7SChris Fraire case '1':
1489b31320a7SChris Fraire primary_opt = _B_TRUE;
1490b31320a7SChris Fraire break;
14916e91bba0SGirish Moodalbail case 'T':
14926e91bba0SGirish Moodalbail atype = optarg;
14936e91bba0SGirish Moodalbail break;
14946e91bba0SGirish Moodalbail case 'a':
14956e91bba0SGirish Moodalbail static_arg = optarg;
14966e91bba0SGirish Moodalbail s_opt = _B_TRUE;
14976e91bba0SGirish Moodalbail break;
14986e91bba0SGirish Moodalbail case 'd':
14996e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_UP;
15006e91bba0SGirish Moodalbail s_opt = _B_TRUE;
15016e91bba0SGirish Moodalbail break;
1502b31320a7SChris Fraire case 'h':
1503b31320a7SChris Fraire reqhost = optarg;
1504b31320a7SChris Fraire break;
15056e91bba0SGirish Moodalbail case 'i':
15066e91bba0SGirish Moodalbail interface_id = optarg;
15076e91bba0SGirish Moodalbail auto_opt = _B_TRUE;
15086e91bba0SGirish Moodalbail break;
15096e91bba0SGirish Moodalbail case 'p':
15106e91bba0SGirish Moodalbail addrconf_arg = optarg;
15116e91bba0SGirish Moodalbail auto_opt = _B_TRUE;
15126e91bba0SGirish Moodalbail break;
15136e91bba0SGirish Moodalbail case 'w':
15146e91bba0SGirish Moodalbail wait = optarg;
15156e91bba0SGirish Moodalbail dhcp_opt = _B_TRUE;
15166e91bba0SGirish Moodalbail break;
15176e91bba0SGirish Moodalbail case 't':
15186e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
15196e91bba0SGirish Moodalbail break;
15206e91bba0SGirish Moodalbail default:
15216e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
15226e91bba0SGirish Moodalbail }
15236e91bba0SGirish Moodalbail }
15246e91bba0SGirish Moodalbail if (atype == NULL || optind != (argc - 1)) {
15256e91bba0SGirish Moodalbail die("Invalid arguments\nusage: %s", use);
15266e91bba0SGirish Moodalbail } else if ((cp = strchr(argv[optind], '/')) == NULL ||
15276e91bba0SGirish Moodalbail strlen(++cp) == 0) {
15286e91bba0SGirish Moodalbail die("invalid address object name: %s\nusage: %s",
15296e91bba0SGirish Moodalbail argv[optind], use);
15306e91bba0SGirish Moodalbail }
15316e91bba0SGirish Moodalbail
15326e91bba0SGirish Moodalbail /*
15336e91bba0SGirish Moodalbail * Allocate and initialize the addrobj based on the address type.
15346e91bba0SGirish Moodalbail */
15356e91bba0SGirish Moodalbail if (strcmp(atype, "static") == 0) {
1536b31320a7SChris Fraire if (static_arg == NULL || auto_opt || dhcp_opt ||
1537b31320a7SChris Fraire reqhost != NULL || primary_opt) {
15386e91bba0SGirish Moodalbail die("Invalid arguments for type %s\nusage: %s",
15396e91bba0SGirish Moodalbail atype, use);
15406e91bba0SGirish Moodalbail }
15416e91bba0SGirish Moodalbail process_static_addrargs(use, static_arg, argv[optind]);
15426e91bba0SGirish Moodalbail } else if (strcmp(atype, "dhcp") == 0) {
15436e91bba0SGirish Moodalbail if (auto_opt || s_opt) {
15446e91bba0SGirish Moodalbail die("Invalid arguments for type %s\nusage: %s",
15456e91bba0SGirish Moodalbail atype, use);
15466e91bba0SGirish Moodalbail }
15476e91bba0SGirish Moodalbail
15486e91bba0SGirish Moodalbail /* Initialize the addrobj for dhcp addresses. */
15496e91bba0SGirish Moodalbail status = ipadm_create_addrobj(IPADM_ADDR_DHCP, argv[optind],
15506e91bba0SGirish Moodalbail &ipaddr);
15516e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
15526e91bba0SGirish Moodalbail die("Error in creating address object: %s",
15536e91bba0SGirish Moodalbail ipadm_status2str(status));
15546e91bba0SGirish Moodalbail }
15556e91bba0SGirish Moodalbail if (wait != NULL) {
15566e91bba0SGirish Moodalbail int32_t ipadm_wait;
15576e91bba0SGirish Moodalbail
15586e91bba0SGirish Moodalbail if (strcmp(wait, "forever") == 0) {
15596e91bba0SGirish Moodalbail ipadm_wait = IPADM_DHCP_WAIT_FOREVER;
15606e91bba0SGirish Moodalbail } else {
15616e91bba0SGirish Moodalbail char *end;
15626e91bba0SGirish Moodalbail long timeout = strtol(wait, &end, 10);
15636e91bba0SGirish Moodalbail
15646e91bba0SGirish Moodalbail if (*end != '\0' || timeout < 0)
15656e91bba0SGirish Moodalbail die("Invalid argument");
15666e91bba0SGirish Moodalbail ipadm_wait = (int32_t)timeout;
15676e91bba0SGirish Moodalbail }
15686e91bba0SGirish Moodalbail status = ipadm_set_wait_time(ipaddr, ipadm_wait);
15696e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
15706e91bba0SGirish Moodalbail die("Error in setting wait time: %s",
15716e91bba0SGirish Moodalbail ipadm_status2str(status));
15726e91bba0SGirish Moodalbail }
15736e91bba0SGirish Moodalbail }
1574b31320a7SChris Fraire if (primary_opt) {
1575b31320a7SChris Fraire status = ipadm_set_primary(ipaddr, _B_TRUE);
1576b31320a7SChris Fraire if (status != IPADM_SUCCESS) {
1577b31320a7SChris Fraire die("Error in setting primary flag: %s",
1578b31320a7SChris Fraire ipadm_status2str(status));
1579b31320a7SChris Fraire }
1580b31320a7SChris Fraire }
1581b31320a7SChris Fraire if (reqhost != NULL) {
1582b31320a7SChris Fraire status = ipadm_set_reqhost(ipaddr, reqhost);
1583b31320a7SChris Fraire if (status != IPADM_SUCCESS) {
1584b31320a7SChris Fraire die("Error in setting reqhost: %s",
1585b31320a7SChris Fraire ipadm_status2str(status));
1586b31320a7SChris Fraire }
1587b31320a7SChris Fraire }
15886e91bba0SGirish Moodalbail } else if (strcmp(atype, "addrconf") == 0) {
1589b31320a7SChris Fraire if (dhcp_opt || s_opt || reqhost != NULL || primary_opt) {
15906e91bba0SGirish Moodalbail die("Invalid arguments for type %s\nusage: %s",
15916e91bba0SGirish Moodalbail atype, use);
15926e91bba0SGirish Moodalbail }
15936e91bba0SGirish Moodalbail
1594b31320a7SChris Fraire /* Initialize the addrobj for ipv6-addrconf addresses. */
15956e91bba0SGirish Moodalbail status = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
15966e91bba0SGirish Moodalbail argv[optind], &ipaddr);
15976e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
15986e91bba0SGirish Moodalbail die("Error in creating address object: %s",
15996e91bba0SGirish Moodalbail ipadm_status2str(status));
16006e91bba0SGirish Moodalbail }
16016e91bba0SGirish Moodalbail if (interface_id != NULL) {
16026e91bba0SGirish Moodalbail status = ipadm_set_interface_id(ipaddr, interface_id);
16036e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
16046e91bba0SGirish Moodalbail die("Error in setting interface ID: %s",
16056e91bba0SGirish Moodalbail ipadm_status2str(status));
16066e91bba0SGirish Moodalbail }
16076e91bba0SGirish Moodalbail }
16086e91bba0SGirish Moodalbail if (addrconf_arg)
16096e91bba0SGirish Moodalbail process_addrconf_addrargs(use, addrconf_arg);
16106e91bba0SGirish Moodalbail } else {
16116e91bba0SGirish Moodalbail die("Invalid address type %s", atype);
16126e91bba0SGirish Moodalbail }
16136e91bba0SGirish Moodalbail
16146e91bba0SGirish Moodalbail status = ipadm_create_addr(iph, ipaddr, flags);
16156e91bba0SGirish Moodalbail if (status == IPADM_DHCP_IPC_TIMEOUT)
16166e91bba0SGirish Moodalbail warn_ipadmerr(status, "");
16176e91bba0SGirish Moodalbail else if (status != IPADM_SUCCESS)
16186e91bba0SGirish Moodalbail die("Could not create address: %s", ipadm_status2str(status));
16196e91bba0SGirish Moodalbail }
16206e91bba0SGirish Moodalbail
16216e91bba0SGirish Moodalbail /*
16226e91bba0SGirish Moodalbail * Used by some address management functions to parse the command line
16236e91bba0SGirish Moodalbail * arguments and create `ipaddr' address object.
16246e91bba0SGirish Moodalbail */
16256e91bba0SGirish Moodalbail static void
process_misc_addrargs(int argc,char * argv[],const char * use,int * index,uint32_t * flags)16266e91bba0SGirish Moodalbail process_misc_addrargs(int argc, char *argv[], const char *use, int *index,
16276e91bba0SGirish Moodalbail uint32_t *flags)
16286e91bba0SGirish Moodalbail {
16296e91bba0SGirish Moodalbail int option;
16306e91bba0SGirish Moodalbail
16316e91bba0SGirish Moodalbail opterr = 0;
16326e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":t", addr_misc_longopts,
16336e91bba0SGirish Moodalbail NULL)) != -1) {
16346e91bba0SGirish Moodalbail switch (option) {
16356e91bba0SGirish Moodalbail case 't':
16366e91bba0SGirish Moodalbail *flags &= ~IPADM_OPT_PERSIST;
16376e91bba0SGirish Moodalbail break;
16386e91bba0SGirish Moodalbail default:
16396e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
16406e91bba0SGirish Moodalbail }
16416e91bba0SGirish Moodalbail }
16426e91bba0SGirish Moodalbail if (optind != (argc - 1))
16436e91bba0SGirish Moodalbail die("Usage: %s", use);
16446e91bba0SGirish Moodalbail
16456e91bba0SGirish Moodalbail *index = optind;
16466e91bba0SGirish Moodalbail }
16476e91bba0SGirish Moodalbail
16486e91bba0SGirish Moodalbail /*
16496e91bba0SGirish Moodalbail * Remove an addrobj from both active and persistent configuration.
16506e91bba0SGirish Moodalbail */
16516e91bba0SGirish Moodalbail static void
do_delete_addr(int argc,char * argv[],const char * use)16526e91bba0SGirish Moodalbail do_delete_addr(int argc, char *argv[], const char *use)
16536e91bba0SGirish Moodalbail {
16546e91bba0SGirish Moodalbail ipadm_status_t status;
1655467e811cSToomas Soome uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
16566e91bba0SGirish Moodalbail int option;
16576e91bba0SGirish Moodalbail
16586e91bba0SGirish Moodalbail opterr = 0;
16596e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":r", addr_misc_longopts,
16606e91bba0SGirish Moodalbail NULL)) != -1) {
16616e91bba0SGirish Moodalbail switch (option) {
16626e91bba0SGirish Moodalbail case 'r':
16636e91bba0SGirish Moodalbail flags |= IPADM_OPT_RELEASE;
16646e91bba0SGirish Moodalbail break;
16656e91bba0SGirish Moodalbail default:
16666e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
16676e91bba0SGirish Moodalbail }
16686e91bba0SGirish Moodalbail }
16696e91bba0SGirish Moodalbail if (optind != (argc - 1))
16706e91bba0SGirish Moodalbail die("Usage: %s", use);
16716e91bba0SGirish Moodalbail
16726e91bba0SGirish Moodalbail status = ipadm_delete_addr(iph, argv[optind], flags);
16736e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
16746e91bba0SGirish Moodalbail die("could not delete address: %s",
16756e91bba0SGirish Moodalbail ipadm_status2str(status));
16766e91bba0SGirish Moodalbail }
16776e91bba0SGirish Moodalbail }
16786e91bba0SGirish Moodalbail
16796e91bba0SGirish Moodalbail /*
16806e91bba0SGirish Moodalbail * Enable an IP address based on the persistent configuration for that
16816e91bba0SGirish Moodalbail * IP address
16826e91bba0SGirish Moodalbail */
16836e91bba0SGirish Moodalbail static void
do_enable_addr(int argc,char * argv[],const char * use)16846e91bba0SGirish Moodalbail do_enable_addr(int argc, char *argv[], const char *use)
16856e91bba0SGirish Moodalbail {
16866e91bba0SGirish Moodalbail ipadm_status_t status;
16876e91bba0SGirish Moodalbail int index;
1688467e811cSToomas Soome uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
16896e91bba0SGirish Moodalbail
16906e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
16916e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
16926e91bba0SGirish Moodalbail die("persistent operation not supported for enable-addr");
16936e91bba0SGirish Moodalbail
16946e91bba0SGirish Moodalbail status = ipadm_enable_addr(iph, argv[index], flags);
16956e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
16966e91bba0SGirish Moodalbail die("could not enable address: %s", ipadm_status2str(status));
16976e91bba0SGirish Moodalbail }
16986e91bba0SGirish Moodalbail
16996e91bba0SGirish Moodalbail /*
17006e91bba0SGirish Moodalbail * Mark the address identified by addrobj 'up'
17016e91bba0SGirish Moodalbail */
17026e91bba0SGirish Moodalbail static void
do_up_addr(int argc,char * argv[],const char * use)17036e91bba0SGirish Moodalbail do_up_addr(int argc, char *argv[], const char *use)
17046e91bba0SGirish Moodalbail {
17056e91bba0SGirish Moodalbail ipadm_status_t status;
17066e91bba0SGirish Moodalbail int index;
1707467e811cSToomas Soome uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
17086e91bba0SGirish Moodalbail
17096e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
17106e91bba0SGirish Moodalbail status = ipadm_up_addr(iph, argv[index], flags);
17116e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
17126e91bba0SGirish Moodalbail die("Could not mark the address up: %s",
17136e91bba0SGirish Moodalbail ipadm_status2str(status));
17146e91bba0SGirish Moodalbail }
17156e91bba0SGirish Moodalbail }
17166e91bba0SGirish Moodalbail
17176e91bba0SGirish Moodalbail /*
17186e91bba0SGirish Moodalbail * Disable the specified addrobj by removing it from active cofiguration
17196e91bba0SGirish Moodalbail */
17206e91bba0SGirish Moodalbail static void
do_disable_addr(int argc,char * argv[],const char * use)17216e91bba0SGirish Moodalbail do_disable_addr(int argc, char *argv[], const char *use)
17226e91bba0SGirish Moodalbail {
17236e91bba0SGirish Moodalbail ipadm_status_t status;
17246e91bba0SGirish Moodalbail int index;
1725467e811cSToomas Soome uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
17266e91bba0SGirish Moodalbail
17276e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
17286e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
17296e91bba0SGirish Moodalbail die("persistent operation not supported for disable-addr");
17306e91bba0SGirish Moodalbail
17316e91bba0SGirish Moodalbail status = ipadm_disable_addr(iph, argv[index], flags);
17326e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
17336e91bba0SGirish Moodalbail die("could not disable address: %s",
17346e91bba0SGirish Moodalbail ipadm_status2str(status));
17356e91bba0SGirish Moodalbail }
17366e91bba0SGirish Moodalbail }
17376e91bba0SGirish Moodalbail
17386e91bba0SGirish Moodalbail /*
17396e91bba0SGirish Moodalbail * Mark the address identified by addrobj 'down'
17406e91bba0SGirish Moodalbail */
17416e91bba0SGirish Moodalbail static void
do_down_addr(int argc,char * argv[],const char * use)17426e91bba0SGirish Moodalbail do_down_addr(int argc, char *argv[], const char *use)
17436e91bba0SGirish Moodalbail {
17446e91bba0SGirish Moodalbail ipadm_status_t status;
17456e91bba0SGirish Moodalbail int index;
1746467e811cSToomas Soome uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
17476e91bba0SGirish Moodalbail
17486e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
17496e91bba0SGirish Moodalbail status = ipadm_down_addr(iph, argv[index], flags);
17506e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
17516e91bba0SGirish Moodalbail die("Could not mark the address down: %s",
17526e91bba0SGirish Moodalbail ipadm_status2str(status));
17536e91bba0SGirish Moodalbail }
17546e91bba0SGirish Moodalbail
17556e91bba0SGirish Moodalbail /*
17566e91bba0SGirish Moodalbail * Restart DAD for static address. Extend lease duration for DHCP addresses
17576e91bba0SGirish Moodalbail */
17586e91bba0SGirish Moodalbail static void
do_refresh_addr(int argc,char * argv[],const char * use)17596e91bba0SGirish Moodalbail do_refresh_addr(int argc, char *argv[], const char *use)
17606e91bba0SGirish Moodalbail {
17616e91bba0SGirish Moodalbail ipadm_status_t status;
17626e91bba0SGirish Moodalbail int option;
17636e91bba0SGirish Moodalbail uint32_t flags = 0;
17646e91bba0SGirish Moodalbail
17656e91bba0SGirish Moodalbail opterr = 0;
17666e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":i", addr_misc_longopts,
17676e91bba0SGirish Moodalbail NULL)) != -1) {
17686e91bba0SGirish Moodalbail switch (option) {
17696e91bba0SGirish Moodalbail case 'i':
17706e91bba0SGirish Moodalbail flags |= IPADM_OPT_INFORM;
17716e91bba0SGirish Moodalbail break;
17726e91bba0SGirish Moodalbail default:
17736e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
17746e91bba0SGirish Moodalbail }
17756e91bba0SGirish Moodalbail }
17766e91bba0SGirish Moodalbail if (optind != (argc - 1))
17776e91bba0SGirish Moodalbail die("Usage: %s", use);
17786e91bba0SGirish Moodalbail
17796e91bba0SGirish Moodalbail status = ipadm_refresh_addr(iph, argv[optind], flags);
17806e91bba0SGirish Moodalbail if (status == IPADM_DHCP_IPC_TIMEOUT)
17816e91bba0SGirish Moodalbail warn_ipadmerr(status, "");
17826e91bba0SGirish Moodalbail else if (status != IPADM_SUCCESS)
17836e91bba0SGirish Moodalbail die("could not refresh address %s", ipadm_status2str(status));
17846e91bba0SGirish Moodalbail }
17856e91bba0SGirish Moodalbail
17866e91bba0SGirish Moodalbail static void
sockaddr2str(const struct sockaddr_storage * ssp,char * buf,uint_t bufsize)17876e91bba0SGirish Moodalbail sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
17886e91bba0SGirish Moodalbail {
17896e91bba0SGirish Moodalbail socklen_t socklen;
17906e91bba0SGirish Moodalbail struct sockaddr *sp = (struct sockaddr *)ssp;
17916e91bba0SGirish Moodalbail
17926e91bba0SGirish Moodalbail switch (ssp->ss_family) {
17936e91bba0SGirish Moodalbail case AF_INET:
17946e91bba0SGirish Moodalbail socklen = sizeof (struct sockaddr_in);
17956e91bba0SGirish Moodalbail break;
17966e91bba0SGirish Moodalbail case AF_INET6:
17976e91bba0SGirish Moodalbail socklen = sizeof (struct sockaddr_in6);
17986e91bba0SGirish Moodalbail break;
17996e91bba0SGirish Moodalbail default:
18006e91bba0SGirish Moodalbail (void) strlcpy(buf, STR_UNKNOWN_VAL, bufsize);
18016e91bba0SGirish Moodalbail return;
18026e91bba0SGirish Moodalbail }
18036e91bba0SGirish Moodalbail
18046e91bba0SGirish Moodalbail (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0,
18056e91bba0SGirish Moodalbail (NI_NOFQDN | NI_NUMERICHOST));
18066e91bba0SGirish Moodalbail }
18076e91bba0SGirish Moodalbail
18086e91bba0SGirish Moodalbail static void
flags2str(uint64_t flags,fmask_t * tbl,boolean_t is_bits,char * buf,uint_t bufsize)18096e91bba0SGirish Moodalbail flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
18106e91bba0SGirish Moodalbail char *buf, uint_t bufsize)
18116e91bba0SGirish Moodalbail {
18126e91bba0SGirish Moodalbail int i;
18136e91bba0SGirish Moodalbail boolean_t first = _B_TRUE;
18146e91bba0SGirish Moodalbail
18156e91bba0SGirish Moodalbail if (is_bits) {
18166e91bba0SGirish Moodalbail for (i = 0; tbl[i].name; i++) {
18176e91bba0SGirish Moodalbail if ((flags & tbl[i].mask) == tbl[i].bits)
18186e91bba0SGirish Moodalbail (void) strlcat(buf, tbl[i].name, bufsize);
18196e91bba0SGirish Moodalbail else
18206e91bba0SGirish Moodalbail (void) strlcat(buf, "-", bufsize);
18216e91bba0SGirish Moodalbail }
18226e91bba0SGirish Moodalbail } else {
18236e91bba0SGirish Moodalbail for (i = 0; tbl[i].name; i++) {
18246e91bba0SGirish Moodalbail if ((flags & tbl[i].mask) == tbl[i].bits) {
18256e91bba0SGirish Moodalbail if (!first)
18266e91bba0SGirish Moodalbail (void) strlcat(buf, ",", bufsize);
18276e91bba0SGirish Moodalbail (void) strlcat(buf, tbl[i].name, bufsize);
18286e91bba0SGirish Moodalbail first = _B_FALSE;
18296e91bba0SGirish Moodalbail }
18306e91bba0SGirish Moodalbail }
18316e91bba0SGirish Moodalbail }
18326e91bba0SGirish Moodalbail }
18336e91bba0SGirish Moodalbail
1834550b6e40SSowmini Varadhan /*
1835550b6e40SSowmini Varadhan * return true if the address for lifname comes to us from the global zone
1836550b6e40SSowmini Varadhan * with 'allowed-ips' constraints.
1837550b6e40SSowmini Varadhan */
1838550b6e40SSowmini Varadhan static boolean_t
is_from_gz(const char * lifname)1839550b6e40SSowmini Varadhan is_from_gz(const char *lifname)
1840550b6e40SSowmini Varadhan {
1841a73be61aSHans Rosenfeld ipadm_if_info_t *if_info;
1842550b6e40SSowmini Varadhan char phyname[LIFNAMSIZ], *cp;
1843550b6e40SSowmini Varadhan boolean_t ret = _B_FALSE;
1844550b6e40SSowmini Varadhan ipadm_status_t status;
1845550b6e40SSowmini Varadhan zoneid_t zoneid;
1846550b6e40SSowmini Varadhan ushort_t zflags;
1847550b6e40SSowmini Varadhan
1848550b6e40SSowmini Varadhan if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
1849550b6e40SSowmini Varadhan return (_B_FALSE); /* from-gz only makes sense in a NGZ */
1850550b6e40SSowmini Varadhan
1851550b6e40SSowmini Varadhan if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
1852550b6e40SSowmini Varadhan return (_B_FALSE);
1853550b6e40SSowmini Varadhan
1854550b6e40SSowmini Varadhan if (!(zflags & ZF_NET_EXCL))
1855550b6e40SSowmini Varadhan return (_B_TRUE); /* everything is from the GZ for shared-ip */
1856550b6e40SSowmini Varadhan
1857550b6e40SSowmini Varadhan (void) strncpy(phyname, lifname, sizeof (phyname));
1858550b6e40SSowmini Varadhan if ((cp = strchr(phyname, ':')) != NULL)
1859550b6e40SSowmini Varadhan *cp = '\0';
1860550b6e40SSowmini Varadhan status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
1861550b6e40SSowmini Varadhan if (status != IPADM_SUCCESS)
1862550b6e40SSowmini Varadhan return (ret);
1863550b6e40SSowmini Varadhan
1864a73be61aSHans Rosenfeld if (if_info->ifi_cflags & IFIF_L3PROTECT)
1865550b6e40SSowmini Varadhan ret = _B_TRUE;
1866cbf54fedSJohn Levon ipadm_free_if_info(if_info);
1867550b6e40SSowmini Varadhan return (ret);
1868550b6e40SSowmini Varadhan }
1869550b6e40SSowmini Varadhan
18706e91bba0SGirish Moodalbail static boolean_t
print_sa_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)18716e91bba0SGirish Moodalbail print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
18726e91bba0SGirish Moodalbail {
18736e91bba0SGirish Moodalbail show_addr_args_t *arg = ofarg->ofmt_cbarg;
18746e91bba0SGirish Moodalbail ipadm_addr_info_t *ainfo = arg->sa_info;
18756e91bba0SGirish Moodalbail char interface[LIFNAMSIZ];
18766e91bba0SGirish Moodalbail char addrbuf[MAXPROPVALLEN];
18776e91bba0SGirish Moodalbail char dstbuf[MAXPROPVALLEN];
18786e91bba0SGirish Moodalbail char prefixlenstr[MAXPROPVALLEN];
18796e91bba0SGirish Moodalbail int prefixlen;
18806e91bba0SGirish Moodalbail struct sockaddr_in *sin;
18816e91bba0SGirish Moodalbail struct sockaddr_in6 *sin6;
18826e91bba0SGirish Moodalbail sa_family_t af;
18836e91bba0SGirish Moodalbail char *phyname = NULL;
18846e91bba0SGirish Moodalbail struct ifaddrs *ifa = &ainfo->ia_ifa;
18856e91bba0SGirish Moodalbail fmask_t cflags_mask[] = {
18866e91bba0SGirish Moodalbail { "U", IA_UP, IA_UP },
18876e91bba0SGirish Moodalbail { "u", IA_UNNUMBERED, IA_UNNUMBERED },
18886e91bba0SGirish Moodalbail { "p", IA_PRIVATE, IA_PRIVATE },
18896e91bba0SGirish Moodalbail { "t", IA_TEMPORARY, IA_TEMPORARY },
18906e91bba0SGirish Moodalbail { "d", IA_DEPRECATED, IA_DEPRECATED },
18916e91bba0SGirish Moodalbail { NULL, 0, 0 }
18926e91bba0SGirish Moodalbail };
18936e91bba0SGirish Moodalbail fmask_t pflags_mask[] = {
18946e91bba0SGirish Moodalbail { "U", IA_UP, IA_UP },
18956e91bba0SGirish Moodalbail { "p", IA_PRIVATE, IA_PRIVATE },
18966e91bba0SGirish Moodalbail { "d", IA_DEPRECATED, IA_DEPRECATED },
18976e91bba0SGirish Moodalbail { NULL, 0, 0 }
18986e91bba0SGirish Moodalbail };
18996e91bba0SGirish Moodalbail fmask_t type[] = {
19006e91bba0SGirish Moodalbail { "static", IPADM_ADDR_STATIC, IPADM_ALL_BITS},
19016e91bba0SGirish Moodalbail { "addrconf", IPADM_ADDR_IPV6_ADDRCONF, IPADM_ALL_BITS},
19026e91bba0SGirish Moodalbail { "dhcp", IPADM_ADDR_DHCP, IPADM_ALL_BITS},
19036e91bba0SGirish Moodalbail { NULL, 0, 0 }
19046e91bba0SGirish Moodalbail };
19056e91bba0SGirish Moodalbail fmask_t addr_state[] = {
19066e91bba0SGirish Moodalbail { "disabled", IFA_DISABLED, IPADM_ALL_BITS},
19076e91bba0SGirish Moodalbail { "duplicate", IFA_DUPLICATE, IPADM_ALL_BITS},
19086e91bba0SGirish Moodalbail { "down", IFA_DOWN, IPADM_ALL_BITS},
19096e91bba0SGirish Moodalbail { "tentative", IFA_TENTATIVE, IPADM_ALL_BITS},
19106e91bba0SGirish Moodalbail { "ok", IFA_OK, IPADM_ALL_BITS},
19116e91bba0SGirish Moodalbail { "inaccessible", IFA_INACCESSIBLE, IPADM_ALL_BITS},
19126e91bba0SGirish Moodalbail { NULL, 0, 0 }
19136e91bba0SGirish Moodalbail };
19146e91bba0SGirish Moodalbail
19156e91bba0SGirish Moodalbail buf[0] = '\0';
19166e91bba0SGirish Moodalbail switch (ofarg->ofmt_id) {
19176e91bba0SGirish Moodalbail case SA_ADDROBJ:
19186e91bba0SGirish Moodalbail if (ainfo->ia_aobjname[0] == '\0') {
19196e91bba0SGirish Moodalbail (void) strncpy(interface, ifa->ifa_name, LIFNAMSIZ);
19206e91bba0SGirish Moodalbail phyname = strrchr(interface, ':');
19216e91bba0SGirish Moodalbail if (phyname)
19226e91bba0SGirish Moodalbail *phyname = '\0';
19236e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s/%s", interface,
19246e91bba0SGirish Moodalbail STR_UNKNOWN_VAL);
19256e91bba0SGirish Moodalbail } else {
19266e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", ainfo->ia_aobjname);
19276e91bba0SGirish Moodalbail }
19286e91bba0SGirish Moodalbail break;
19296e91bba0SGirish Moodalbail case SA_STATE:
19306e91bba0SGirish Moodalbail flags2str(ainfo->ia_state, addr_state, _B_FALSE,
19316e91bba0SGirish Moodalbail buf, bufsize);
19326e91bba0SGirish Moodalbail break;
19336e91bba0SGirish Moodalbail case SA_TYPE:
1934550b6e40SSowmini Varadhan if (is_from_gz(ifa->ifa_name))
1935550b6e40SSowmini Varadhan (void) snprintf(buf, bufsize, "from-gz");
1936550b6e40SSowmini Varadhan else
1937550b6e40SSowmini Varadhan flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
1938550b6e40SSowmini Varadhan bufsize);
19396e91bba0SGirish Moodalbail break;
19406e91bba0SGirish Moodalbail case SA_CURRENT:
19416e91bba0SGirish Moodalbail flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
19426e91bba0SGirish Moodalbail break;
19436e91bba0SGirish Moodalbail case SA_PERSISTENT:
19446e91bba0SGirish Moodalbail flags2str(ainfo->ia_pflags, pflags_mask, _B_TRUE, buf, bufsize);
19456e91bba0SGirish Moodalbail break;
19466e91bba0SGirish Moodalbail case SA_ADDR:
194764639aafSDarren Reed af = ifa->ifa_addr->sa_family;
19486e91bba0SGirish Moodalbail /*
19496e91bba0SGirish Moodalbail * If the address is 0.0.0.0 or :: and the origin is DHCP,
19506e91bba0SGirish Moodalbail * print STR_UNKNOWN_VAL.
19516e91bba0SGirish Moodalbail */
19526e91bba0SGirish Moodalbail if (ainfo->ia_atype == IPADM_ADDR_DHCP) {
19536e91bba0SGirish Moodalbail sin = (struct sockaddr_in *)ifa->ifa_addr;
19546e91bba0SGirish Moodalbail sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
19556e91bba0SGirish Moodalbail if ((af == AF_INET &&
19566e91bba0SGirish Moodalbail sin->sin_addr.s_addr == INADDR_ANY) ||
19576e91bba0SGirish Moodalbail (af == AF_INET6 &&
19586e91bba0SGirish Moodalbail IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
19596e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, STR_UNKNOWN_VAL);
19606e91bba0SGirish Moodalbail break;
19616e91bba0SGirish Moodalbail }
19626e91bba0SGirish Moodalbail }
19636e91bba0SGirish Moodalbail if (ifa->ifa_netmask == NULL)
19646e91bba0SGirish Moodalbail prefixlen = 0;
19656e91bba0SGirish Moodalbail else
19666e91bba0SGirish Moodalbail prefixlen = mask2plen(ifa->ifa_netmask);
19676e91bba0SGirish Moodalbail bzero(prefixlenstr, sizeof (prefixlenstr));
19686e91bba0SGirish Moodalbail if (prefixlen > 0) {
19696e91bba0SGirish Moodalbail (void) snprintf(prefixlenstr, sizeof (prefixlenstr),
19706e91bba0SGirish Moodalbail "/%d", prefixlen);
19716e91bba0SGirish Moodalbail }
19726e91bba0SGirish Moodalbail bzero(addrbuf, sizeof (addrbuf));
19736e91bba0SGirish Moodalbail bzero(dstbuf, sizeof (dstbuf));
19746e91bba0SGirish Moodalbail if (ainfo->ia_atype == IPADM_ADDR_STATIC) {
19756e91bba0SGirish Moodalbail /*
19766e91bba0SGirish Moodalbail * Print the hostname fields if the address is not
19776e91bba0SGirish Moodalbail * in active configuration.
19786e91bba0SGirish Moodalbail */
19796e91bba0SGirish Moodalbail if (ainfo->ia_state == IFA_DISABLED) {
19806e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s",
19816e91bba0SGirish Moodalbail ainfo->ia_sname);
19826e91bba0SGirish Moodalbail if (ainfo->ia_dname[0] != '\0') {
19836e91bba0SGirish Moodalbail (void) snprintf(dstbuf, sizeof (dstbuf),
19846e91bba0SGirish Moodalbail "->%s", ainfo->ia_dname);
19856e91bba0SGirish Moodalbail (void) strlcat(buf, dstbuf, bufsize);
19866e91bba0SGirish Moodalbail } else {
19876e91bba0SGirish Moodalbail (void) strlcat(buf, prefixlenstr,
19886e91bba0SGirish Moodalbail bufsize);
19896e91bba0SGirish Moodalbail }
19906e91bba0SGirish Moodalbail break;
19916e91bba0SGirish Moodalbail }
19926e91bba0SGirish Moodalbail }
199308ed54f3SVasumathi Sundaram /*
199408ed54f3SVasumathi Sundaram * For the non-persistent case, we need to show the
199508ed54f3SVasumathi Sundaram * currently configured addresses for source and
199608ed54f3SVasumathi Sundaram * destination.
199708ed54f3SVasumathi Sundaram */
19986e91bba0SGirish Moodalbail sockaddr2str((struct sockaddr_storage *)ifa->ifa_addr,
19996e91bba0SGirish Moodalbail addrbuf, sizeof (addrbuf));
200008ed54f3SVasumathi Sundaram if (ifa->ifa_flags & IFF_POINTOPOINT) {
200108ed54f3SVasumathi Sundaram sockaddr2str(
200208ed54f3SVasumathi Sundaram (struct sockaddr_storage *)ifa->ifa_dstaddr,
200308ed54f3SVasumathi Sundaram dstbuf, sizeof (dstbuf));
20046e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s->%s", addrbuf,
20056e91bba0SGirish Moodalbail dstbuf);
20066e91bba0SGirish Moodalbail } else {
20076e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s%s", addrbuf,
20086e91bba0SGirish Moodalbail prefixlenstr);
20096e91bba0SGirish Moodalbail }
20106e91bba0SGirish Moodalbail break;
20116e91bba0SGirish Moodalbail default:
20126e91bba0SGirish Moodalbail die("invalid input");
20136e91bba0SGirish Moodalbail break;
20146e91bba0SGirish Moodalbail }
20156e91bba0SGirish Moodalbail
20166e91bba0SGirish Moodalbail return (_B_TRUE);
20176e91bba0SGirish Moodalbail }
20186e91bba0SGirish Moodalbail
20196e91bba0SGirish Moodalbail /*
20206e91bba0SGirish Moodalbail * Display address information, either for the given address or
20216e91bba0SGirish Moodalbail * for all the addresses managed by ipadm.
20226e91bba0SGirish Moodalbail */
20236e91bba0SGirish Moodalbail static void
do_show_addr(int argc,char * argv[],const char * use)20246e91bba0SGirish Moodalbail do_show_addr(int argc, char *argv[], const char *use)
20256e91bba0SGirish Moodalbail {
20266e91bba0SGirish Moodalbail ipadm_status_t status;
20276e91bba0SGirish Moodalbail show_addr_state_t state;
20286e91bba0SGirish Moodalbail char *def_fields_str = "addrobj,type,state,addr";
20296e91bba0SGirish Moodalbail char *fields_str = NULL;
20306e91bba0SGirish Moodalbail ipadm_addr_info_t *ainfo;
20316e91bba0SGirish Moodalbail ipadm_addr_info_t *ptr;
20326e91bba0SGirish Moodalbail show_addr_args_t sargs;
20336e91bba0SGirish Moodalbail int option;
20346e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
20356e91bba0SGirish Moodalbail ofmt_status_t oferr;
20366e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
20376e91bba0SGirish Moodalbail char *aname;
20386e91bba0SGirish Moodalbail char *ifname = NULL;
20396e91bba0SGirish Moodalbail char *cp;
20406e91bba0SGirish Moodalbail boolean_t found = _B_FALSE;
20416e91bba0SGirish Moodalbail
20426e91bba0SGirish Moodalbail opterr = 0;
20436e91bba0SGirish Moodalbail state.sa_parsable = _B_FALSE;
20446e91bba0SGirish Moodalbail state.sa_persist = _B_FALSE;
20456e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, "po:", show_addr_longopts,
20466e91bba0SGirish Moodalbail NULL)) != -1) {
20476e91bba0SGirish Moodalbail switch (option) {
20486e91bba0SGirish Moodalbail case 'p':
20496e91bba0SGirish Moodalbail state.sa_parsable = _B_TRUE;
20506e91bba0SGirish Moodalbail break;
20516e91bba0SGirish Moodalbail case 'o':
20526e91bba0SGirish Moodalbail fields_str = optarg;
20536e91bba0SGirish Moodalbail break;
20546e91bba0SGirish Moodalbail default:
20556e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
20566e91bba0SGirish Moodalbail break;
20576e91bba0SGirish Moodalbail }
20586e91bba0SGirish Moodalbail }
20596e91bba0SGirish Moodalbail if (state.sa_parsable && fields_str == NULL)
20606e91bba0SGirish Moodalbail die("-p requires -o");
20616e91bba0SGirish Moodalbail
20626e91bba0SGirish Moodalbail if (optind == argc - 1) {
20636e91bba0SGirish Moodalbail aname = argv[optind];
20646e91bba0SGirish Moodalbail if ((cp = strchr(aname, '/')) == NULL)
20656e91bba0SGirish Moodalbail die("Invalid address object name provided");
20666e91bba0SGirish Moodalbail if (*(cp + 1) == '\0') {
20676e91bba0SGirish Moodalbail ifname = aname;
20686e91bba0SGirish Moodalbail *cp = '\0';
20696e91bba0SGirish Moodalbail aname = NULL;
20706e91bba0SGirish Moodalbail }
20716e91bba0SGirish Moodalbail } else if (optind == argc) {
20726e91bba0SGirish Moodalbail aname = NULL;
20736e91bba0SGirish Moodalbail } else {
20746e91bba0SGirish Moodalbail die("Usage: %s", use);
20756e91bba0SGirish Moodalbail }
20766e91bba0SGirish Moodalbail
20776e91bba0SGirish Moodalbail if (state.sa_parsable)
20786e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
20796e91bba0SGirish Moodalbail if (fields_str == NULL)
20806e91bba0SGirish Moodalbail fields_str = def_fields_str;
20816e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
20826e91bba0SGirish Moodalbail
2083b2f26520SBryan Cantrill ofmt_check(oferr, state.sa_parsable, ofmt, die, warn);
20846e91bba0SGirish Moodalbail state.sa_ofmt = ofmt;
20856e91bba0SGirish Moodalbail
20866e91bba0SGirish Moodalbail status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
20876e91bba0SGirish Moodalbail /*
20886e91bba0SGirish Moodalbail * Return without printing any error, if no addresses were found,
20896e91bba0SGirish Moodalbail * for the case where all addresses are requested.
20906e91bba0SGirish Moodalbail */
20916e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
20926e91bba0SGirish Moodalbail die("Could not get address: %s", ipadm_status2str(status));
20936e91bba0SGirish Moodalbail if (ainfo == NULL) {
20946e91bba0SGirish Moodalbail ofmt_close(ofmt);
20956e91bba0SGirish Moodalbail return;
20966e91bba0SGirish Moodalbail }
20976e91bba0SGirish Moodalbail
20986e91bba0SGirish Moodalbail bzero(&sargs, sizeof (sargs));
20996e91bba0SGirish Moodalbail sargs.sa_state = &state;
21006e91bba0SGirish Moodalbail for (ptr = ainfo; ptr != NULL; ptr = IA_NEXT(ptr)) {
21016e91bba0SGirish Moodalbail sargs.sa_info = ptr;
21026e91bba0SGirish Moodalbail if (aname != NULL) {
21036e91bba0SGirish Moodalbail if (strcmp(sargs.sa_info->ia_aobjname, aname) != 0)
21046e91bba0SGirish Moodalbail continue;
21056e91bba0SGirish Moodalbail found = _B_TRUE;
21066e91bba0SGirish Moodalbail }
21076e91bba0SGirish Moodalbail ofmt_print(state.sa_ofmt, &sargs);
21086e91bba0SGirish Moodalbail }
21096e91bba0SGirish Moodalbail if (ainfo)
21106e91bba0SGirish Moodalbail ipadm_free_addr_info(ainfo);
21116e91bba0SGirish Moodalbail if (aname != NULL && !found)
21126e91bba0SGirish Moodalbail die("Address object not found");
21136e91bba0SGirish Moodalbail }
21146e91bba0SGirish Moodalbail
21156e91bba0SGirish Moodalbail static boolean_t
print_si_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)21166e91bba0SGirish Moodalbail print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
21176e91bba0SGirish Moodalbail {
21186e91bba0SGirish Moodalbail show_if_args_t *arg = ofarg->ofmt_cbarg;
2119a73be61aSHans Rosenfeld ipadm_if_info_t *ifinfo = arg->si_info;
2120a73be61aSHans Rosenfeld char *ifname = ifinfo->ifi_name;
21216e91bba0SGirish Moodalbail fmask_t intf_state[] = {
21226e91bba0SGirish Moodalbail { "ok", IFIS_OK, IPADM_ALL_BITS},
21236e91bba0SGirish Moodalbail { "down", IFIS_DOWN, IPADM_ALL_BITS},
21246e91bba0SGirish Moodalbail { "disabled", IFIS_DISABLED, IPADM_ALL_BITS},
21256e91bba0SGirish Moodalbail { "failed", IFIS_FAILED, IPADM_ALL_BITS},
21266e91bba0SGirish Moodalbail { "offline", IFIS_OFFLINE, IPADM_ALL_BITS},
21276e91bba0SGirish Moodalbail { NULL, 0, 0 }
21286e91bba0SGirish Moodalbail };
21296e91bba0SGirish Moodalbail fmask_t intf_pflags[] = {
21306e91bba0SGirish Moodalbail { "s", IFIF_STANDBY, IFIF_STANDBY },
21316e91bba0SGirish Moodalbail { "4", IFIF_IPV4, IFIF_IPV4 },
21326e91bba0SGirish Moodalbail { "6", IFIF_IPV6, IFIF_IPV6 },
21336e91bba0SGirish Moodalbail { NULL, 0, 0 }
21346e91bba0SGirish Moodalbail };
21356e91bba0SGirish Moodalbail fmask_t intf_cflags[] = {
21366e91bba0SGirish Moodalbail { "b", IFIF_BROADCAST, IFIF_BROADCAST },
21376e91bba0SGirish Moodalbail { "m", IFIF_MULTICAST, IFIF_MULTICAST },
21386e91bba0SGirish Moodalbail { "p", IFIF_POINTOPOINT, IFIF_POINTOPOINT},
21396e91bba0SGirish Moodalbail { "v", IFIF_VIRTUAL, IFIF_VIRTUAL },
21406e91bba0SGirish Moodalbail { "I", IFIF_IPMP, IFIF_IPMP },
21416e91bba0SGirish Moodalbail { "s", IFIF_STANDBY, IFIF_STANDBY },
21426e91bba0SGirish Moodalbail { "i", IFIF_INACTIVE, IFIF_INACTIVE },
21436e91bba0SGirish Moodalbail { "V", IFIF_VRRP, IFIF_VRRP },
21446e91bba0SGirish Moodalbail { "a", IFIF_NOACCEPT, IFIF_NOACCEPT },
2145550b6e40SSowmini Varadhan { "Z", IFIF_L3PROTECT, IFIF_L3PROTECT },
21466e91bba0SGirish Moodalbail { "4", IFIF_IPV4, IFIF_IPV4 },
21476e91bba0SGirish Moodalbail { "6", IFIF_IPV6, IFIF_IPV6 },
21486e91bba0SGirish Moodalbail { NULL, 0, 0 }
21496e91bba0SGirish Moodalbail };
2150a73be61aSHans Rosenfeld fmask_t intf_class[] = {
2151a73be61aSHans Rosenfeld { "IP", IPADM_IF_CLASS_REGULAR, IPADM_ALL_BITS},
2152a73be61aSHans Rosenfeld { "IPMP", IPADM_IF_CLASS_IPMP, IPADM_ALL_BITS},
2153a73be61aSHans Rosenfeld { "VIRTUAL", IPADM_IF_CLASS_VIRTUAL, IPADM_ALL_BITS},
2154a73be61aSHans Rosenfeld { "UNKNOWN", IPADM_IF_CLASS_UNKNOWN, IPADM_ALL_BITS},
2155a73be61aSHans Rosenfeld { NULL, 0, 0}
2156a73be61aSHans Rosenfeld };
21576e91bba0SGirish Moodalbail
21586e91bba0SGirish Moodalbail buf[0] = '\0';
21596e91bba0SGirish Moodalbail switch (ofarg->ofmt_id) {
21606e91bba0SGirish Moodalbail case SI_IFNAME:
21616e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", ifname);
21626e91bba0SGirish Moodalbail break;
2163a73be61aSHans Rosenfeld case SI_IFCLASS:
2164a73be61aSHans Rosenfeld flags2str(ifinfo->ifi_class, intf_class, _B_FALSE,
2165a73be61aSHans Rosenfeld buf, bufsize);
2166a73be61aSHans Rosenfeld break;
21676e91bba0SGirish Moodalbail case SI_STATE:
2168a73be61aSHans Rosenfeld flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
21696e91bba0SGirish Moodalbail buf, bufsize);
21706e91bba0SGirish Moodalbail break;
21716e91bba0SGirish Moodalbail case SI_CURRENT:
2172a73be61aSHans Rosenfeld flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
21736e91bba0SGirish Moodalbail buf, bufsize);
21746e91bba0SGirish Moodalbail break;
21756e91bba0SGirish Moodalbail case SI_PERSISTENT:
2176a73be61aSHans Rosenfeld flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
21776e91bba0SGirish Moodalbail buf, bufsize);
21786e91bba0SGirish Moodalbail break;
21796e91bba0SGirish Moodalbail default:
21806e91bba0SGirish Moodalbail die("invalid input");
21816e91bba0SGirish Moodalbail break;
21826e91bba0SGirish Moodalbail }
21836e91bba0SGirish Moodalbail
21846e91bba0SGirish Moodalbail return (_B_TRUE);
21856e91bba0SGirish Moodalbail }
21866e91bba0SGirish Moodalbail
21876e91bba0SGirish Moodalbail /*
21886e91bba0SGirish Moodalbail * Display interface information, either for the given interface or
21896e91bba0SGirish Moodalbail * for all the interfaces in the system.
21906e91bba0SGirish Moodalbail */
21916e91bba0SGirish Moodalbail static void
do_show_if(int argc,char * argv[],const char * use)21926e91bba0SGirish Moodalbail do_show_if(int argc, char *argv[], const char *use)
21936e91bba0SGirish Moodalbail {
21946e91bba0SGirish Moodalbail ipadm_status_t status;
21956e91bba0SGirish Moodalbail show_if_state_t state;
21966e91bba0SGirish Moodalbail char *fields_str = NULL;
2197a73be61aSHans Rosenfeld ipadm_if_info_t *if_info, *ptr;
21986e91bba0SGirish Moodalbail show_if_args_t sargs;
21996e91bba0SGirish Moodalbail int option;
22006e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
22016e91bba0SGirish Moodalbail ofmt_status_t oferr;
22026e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
22036e91bba0SGirish Moodalbail char *ifname = NULL;
22046e91bba0SGirish Moodalbail
22056e91bba0SGirish Moodalbail opterr = 0;
22066e91bba0SGirish Moodalbail state.si_parsable = _B_FALSE;
22076e91bba0SGirish Moodalbail
22086e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, "po:", show_if_longopts,
22096e91bba0SGirish Moodalbail NULL)) != -1) {
22106e91bba0SGirish Moodalbail switch (option) {
22116e91bba0SGirish Moodalbail case 'p':
22126e91bba0SGirish Moodalbail state.si_parsable = _B_TRUE;
22136e91bba0SGirish Moodalbail break;
22146e91bba0SGirish Moodalbail case 'o':
22156e91bba0SGirish Moodalbail fields_str = optarg;
22166e91bba0SGirish Moodalbail break;
22176e91bba0SGirish Moodalbail default:
22186e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
22196e91bba0SGirish Moodalbail break;
22206e91bba0SGirish Moodalbail }
22216e91bba0SGirish Moodalbail }
22226e91bba0SGirish Moodalbail if (optind == argc - 1)
22236e91bba0SGirish Moodalbail ifname = argv[optind];
22246e91bba0SGirish Moodalbail else if (optind != argc)
22256e91bba0SGirish Moodalbail die("Usage: %s", use);
22266e91bba0SGirish Moodalbail if (state.si_parsable)
22276e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
22286e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
2229b2f26520SBryan Cantrill ofmt_check(oferr, state.si_parsable, ofmt, die, warn);
22306e91bba0SGirish Moodalbail state.si_ofmt = ofmt;
22316e91bba0SGirish Moodalbail bzero(&sargs, sizeof (sargs));
22326e91bba0SGirish Moodalbail sargs.si_state = &state;
22336e91bba0SGirish Moodalbail status = ipadm_if_info(iph, ifname, &if_info, 0, LIFC_DEFAULT);
22346e91bba0SGirish Moodalbail /*
22356e91bba0SGirish Moodalbail * Return without printing any error, if no addresses were found.
22366e91bba0SGirish Moodalbail */
22376e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
22386e91bba0SGirish Moodalbail die("Could not get interface(s): %s",
22396e91bba0SGirish Moodalbail ipadm_status2str(status));
22406e91bba0SGirish Moodalbail }
22416e91bba0SGirish Moodalbail
2242a73be61aSHans Rosenfeld for (ptr = if_info; ptr != NULL; ptr = ptr->ifi_next) {
22436e91bba0SGirish Moodalbail sargs.si_info = ptr;
22446e91bba0SGirish Moodalbail ofmt_print(state.si_ofmt, &sargs);
22456e91bba0SGirish Moodalbail }
22466e91bba0SGirish Moodalbail if (if_info)
22476e91bba0SGirish Moodalbail ipadm_free_if_info(if_info);
22486e91bba0SGirish Moodalbail }
22496e91bba0SGirish Moodalbail
22506e91bba0SGirish Moodalbail /*
22516e91bba0SGirish Moodalbail * set/reset the address property for a given address
22526e91bba0SGirish Moodalbail */
22536e91bba0SGirish Moodalbail static void
set_addrprop(int argc,char ** argv,boolean_t reset,const char * use)22546e91bba0SGirish Moodalbail set_addrprop(int argc, char **argv, boolean_t reset, const char *use)
22556e91bba0SGirish Moodalbail {
2256467e811cSToomas Soome int option;
2257467e811cSToomas Soome ipadm_status_t status = IPADM_SUCCESS;
2258467e811cSToomas Soome boolean_t p_arg = _B_FALSE;
2259467e811cSToomas Soome char *nv, *aobjname;
22606e91bba0SGirish Moodalbail char *prop_name, *prop_val;
22616e91bba0SGirish Moodalbail uint_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
22626e91bba0SGirish Moodalbail
2263467e811cSToomas Soome nv = NULL;
22646e91bba0SGirish Moodalbail opterr = 0;
22656e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":i:p:t", set_ifprop_longopts,
22666e91bba0SGirish Moodalbail NULL)) != -1) {
22676e91bba0SGirish Moodalbail switch (option) {
22686e91bba0SGirish Moodalbail case 'p':
22696e91bba0SGirish Moodalbail if (p_arg)
22706e91bba0SGirish Moodalbail die("-p must be specified once only");
22716e91bba0SGirish Moodalbail p_arg = _B_TRUE;
22726e91bba0SGirish Moodalbail
22736e91bba0SGirish Moodalbail ipadm_check_propstr(optarg, reset, use);
22746e91bba0SGirish Moodalbail nv = optarg;
22756e91bba0SGirish Moodalbail break;
22766e91bba0SGirish Moodalbail case 't':
22776e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
22786e91bba0SGirish Moodalbail break;
22796e91bba0SGirish Moodalbail default:
22806e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
22816e91bba0SGirish Moodalbail }
22826e91bba0SGirish Moodalbail }
22836e91bba0SGirish Moodalbail
22846e91bba0SGirish Moodalbail if (!p_arg || optind != (argc - 1))
22856e91bba0SGirish Moodalbail die("Usage: %s", use);
22866e91bba0SGirish Moodalbail
22876e91bba0SGirish Moodalbail prop_name = nv;
22886e91bba0SGirish Moodalbail prop_val = strchr(nv, '=');
22896e91bba0SGirish Moodalbail if (prop_val != NULL)
22906e91bba0SGirish Moodalbail *prop_val++ = '\0';
22916e91bba0SGirish Moodalbail aobjname = argv[optind];
22926e91bba0SGirish Moodalbail if (reset)
22936e91bba0SGirish Moodalbail flags |= IPADM_OPT_DEFAULT;
22946e91bba0SGirish Moodalbail status = ipadm_set_addrprop(iph, prop_name, prop_val, aobjname, flags);
22956e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
22966e91bba0SGirish Moodalbail if (reset)
22976e91bba0SGirish Moodalbail die("reset-addrprop: %s: %s", prop_name,
22986e91bba0SGirish Moodalbail ipadm_status2str(status));
22996e91bba0SGirish Moodalbail else
23006e91bba0SGirish Moodalbail die("set-addrprop: %s: %s", prop_name,
23016e91bba0SGirish Moodalbail ipadm_status2str(status));
23026e91bba0SGirish Moodalbail }
23036e91bba0SGirish Moodalbail }
23046e91bba0SGirish Moodalbail
23056e91bba0SGirish Moodalbail /*
23066e91bba0SGirish Moodalbail * Sets a property on an address object.
23076e91bba0SGirish Moodalbail */
23086e91bba0SGirish Moodalbail static void
do_set_addrprop(int argc,char ** argv,const char * use)23096e91bba0SGirish Moodalbail do_set_addrprop(int argc, char **argv, const char *use)
23106e91bba0SGirish Moodalbail {
23116e91bba0SGirish Moodalbail set_addrprop(argc, argv, _B_FALSE, use);
23126e91bba0SGirish Moodalbail }
23136e91bba0SGirish Moodalbail
23146e91bba0SGirish Moodalbail /*
23156e91bba0SGirish Moodalbail * Resets a property to its default value on an address object.
23166e91bba0SGirish Moodalbail */
23176e91bba0SGirish Moodalbail static void
do_reset_addrprop(int argc,char ** argv,const char * use)23186e91bba0SGirish Moodalbail do_reset_addrprop(int argc, char **argv, const char *use)
23196e91bba0SGirish Moodalbail {
23206e91bba0SGirish Moodalbail set_addrprop(argc, argv, _B_TRUE, use);
23216e91bba0SGirish Moodalbail }
23226e91bba0SGirish Moodalbail
23236e91bba0SGirish Moodalbail /*
23246e91bba0SGirish Moodalbail * Display information for all or specific address properties, either for a
23256e91bba0SGirish Moodalbail * given address or for all the addresses in the system.
23266e91bba0SGirish Moodalbail */
23276e91bba0SGirish Moodalbail static void
do_show_addrprop(int argc,char * argv[],const char * use)23286e91bba0SGirish Moodalbail do_show_addrprop(int argc, char *argv[], const char *use)
23296e91bba0SGirish Moodalbail {
2330467e811cSToomas Soome int option;
2331467e811cSToomas Soome nvlist_t *proplist = NULL;
23326e91bba0SGirish Moodalbail char *fields_str = NULL;
2333467e811cSToomas Soome show_prop_state_t state;
23346e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
23356e91bba0SGirish Moodalbail ofmt_status_t oferr;
23366e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
23378c8556f9SYuri Pankov char *aobjname = NULL;
23386e91bba0SGirish Moodalbail char *ifname = NULL;
23396e91bba0SGirish Moodalbail char *cp;
23408c8556f9SYuri Pankov ipadm_addr_info_t *ainfop = NULL;
23418c8556f9SYuri Pankov ipadm_addr_info_t *ptr;
23428c8556f9SYuri Pankov ipadm_status_t status;
23438c8556f9SYuri Pankov boolean_t found = _B_FALSE;
23446e91bba0SGirish Moodalbail
23456e91bba0SGirish Moodalbail opterr = 0;
23466e91bba0SGirish Moodalbail bzero(&state, sizeof (state));
23476e91bba0SGirish Moodalbail state.sps_propval = NULL;
23486e91bba0SGirish Moodalbail state.sps_parsable = _B_FALSE;
23496e91bba0SGirish Moodalbail state.sps_addrprop = _B_TRUE;
23506e91bba0SGirish Moodalbail state.sps_proto = MOD_PROTO_NONE;
23516e91bba0SGirish Moodalbail state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
23526e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:i:cPo:",
23536e91bba0SGirish Moodalbail show_prop_longopts, NULL)) != -1) {
23546e91bba0SGirish Moodalbail switch (option) {
23556e91bba0SGirish Moodalbail case 'p':
23566e91bba0SGirish Moodalbail if (ipadm_str2nvlist(optarg, &proplist,
23576e91bba0SGirish Moodalbail IPADM_NORVAL) != 0)
23588c8556f9SYuri Pankov die("invalid addrobj properties specified");
23596e91bba0SGirish Moodalbail break;
23606e91bba0SGirish Moodalbail case 'c':
23616e91bba0SGirish Moodalbail state.sps_parsable = _B_TRUE;
23626e91bba0SGirish Moodalbail break;
23636e91bba0SGirish Moodalbail case 'o':
23646e91bba0SGirish Moodalbail fields_str = optarg;
23656e91bba0SGirish Moodalbail break;
23666e91bba0SGirish Moodalbail default:
23676e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
23686e91bba0SGirish Moodalbail break;
23696e91bba0SGirish Moodalbail }
23706e91bba0SGirish Moodalbail }
23716e91bba0SGirish Moodalbail if (optind == argc - 1) {
23726e91bba0SGirish Moodalbail aobjname = argv[optind];
23736e91bba0SGirish Moodalbail cp = strchr(aobjname, '/');
23746e91bba0SGirish Moodalbail if (cp == NULL)
23758c8556f9SYuri Pankov die("invalid addrobj name provided");
23766e91bba0SGirish Moodalbail if (*(cp + 1) == '\0') {
23776e91bba0SGirish Moodalbail ifname = aobjname;
23786e91bba0SGirish Moodalbail *cp = '\0';
23796e91bba0SGirish Moodalbail aobjname = NULL;
23806e91bba0SGirish Moodalbail }
23818c8556f9SYuri Pankov } else if (optind != argc) {
23826e91bba0SGirish Moodalbail die("Usage: %s", use);
23836e91bba0SGirish Moodalbail }
23846e91bba0SGirish Moodalbail state.sps_proplist = proplist;
23856e91bba0SGirish Moodalbail if (state.sps_parsable)
23866e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
23876e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
2388b2f26520SBryan Cantrill ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
23896e91bba0SGirish Moodalbail state.sps_ofmt = ofmt;
23906e91bba0SGirish Moodalbail
23918c8556f9SYuri Pankov status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
23928c8556f9SYuri Pankov /* Return without printing any error, if no addresses were found */
23938c8556f9SYuri Pankov if (status == IPADM_NOTFOUND)
23948c8556f9SYuri Pankov return;
23958c8556f9SYuri Pankov if (status != IPADM_SUCCESS)
23968c8556f9SYuri Pankov die("error retrieving address: %s", ipadm_status2str(status));
23976e91bba0SGirish Moodalbail
23988c8556f9SYuri Pankov for (ptr = ainfop; ptr != NULL; ptr = IA_NEXT(ptr)) {
23998c8556f9SYuri Pankov char *taobjname = ptr->ia_aobjname;
24008c8556f9SYuri Pankov
24018c8556f9SYuri Pankov if (taobjname[0] == '\0')
24028c8556f9SYuri Pankov continue;
24038c8556f9SYuri Pankov if (aobjname != NULL) {
24048c8556f9SYuri Pankov if (strcmp(aobjname, taobjname) == 0)
24058c8556f9SYuri Pankov found = _B_TRUE;
24068c8556f9SYuri Pankov else
24078c8556f9SYuri Pankov continue;
24086e91bba0SGirish Moodalbail }
24098c8556f9SYuri Pankov if (ptr->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
24108c8556f9SYuri Pankov if (found)
24118c8556f9SYuri Pankov break;
24128c8556f9SYuri Pankov else
24136e91bba0SGirish Moodalbail continue;
24146e91bba0SGirish Moodalbail }
24158c8556f9SYuri Pankov (void) strlcpy(state.sps_aobjname, taobjname,
24168c8556f9SYuri Pankov sizeof (state.sps_aobjname));
24178c8556f9SYuri Pankov show_properties(&state, IPADMPROP_CLASS_ADDR);
24188c8556f9SYuri Pankov if (found)
24198c8556f9SYuri Pankov break;
24206e91bba0SGirish Moodalbail }
24218c8556f9SYuri Pankov ipadm_free_addr_info(ainfop);
24228c8556f9SYuri Pankov
24238c8556f9SYuri Pankov if (aobjname != NULL && !found)
24248c8556f9SYuri Pankov die("addrobj not found: %s", aobjname);
24258c8556f9SYuri Pankov
24266e91bba0SGirish Moodalbail nvlist_free(proplist);
24276e91bba0SGirish Moodalbail ofmt_close(ofmt);
24286e91bba0SGirish Moodalbail if (state.sps_retstatus != IPADM_SUCCESS) {
24296e91bba0SGirish Moodalbail ipadm_close(iph);
24306e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
24316e91bba0SGirish Moodalbail }
24326e91bba0SGirish Moodalbail }
24336e91bba0SGirish Moodalbail
24346e91bba0SGirish Moodalbail /*
24356e91bba0SGirish Moodalbail * check if the `pstr' adheres to following syntax
24366e91bba0SGirish Moodalbail * - prop=<value[,...]> (for set)
24376e91bba0SGirish Moodalbail * - prop (for reset)
24386e91bba0SGirish Moodalbail */
24396e91bba0SGirish Moodalbail static void
ipadm_check_propstr(const char * pstr,boolean_t reset,const char * use)24406e91bba0SGirish Moodalbail ipadm_check_propstr(const char *pstr, boolean_t reset, const char *use)
24416e91bba0SGirish Moodalbail {
24426e91bba0SGirish Moodalbail char *nv;
24436e91bba0SGirish Moodalbail
24446e91bba0SGirish Moodalbail nv = strchr(pstr, '=');
24456e91bba0SGirish Moodalbail if (reset) {
24466e91bba0SGirish Moodalbail if (nv != NULL)
24476e91bba0SGirish Moodalbail die("incorrect syntax used for -p.\n%s", use);
24486e91bba0SGirish Moodalbail } else {
24496e91bba0SGirish Moodalbail if (nv == NULL || *++nv == '\0')
24506e91bba0SGirish Moodalbail die("please specify the value to be set.\n%s", use);
24516e91bba0SGirish Moodalbail nv = strchr(nv, '=');
24526e91bba0SGirish Moodalbail /* cannot have multiple 'prop=val' for single -p */
24536e91bba0SGirish Moodalbail if (nv != NULL)
24546e91bba0SGirish Moodalbail die("cannot specify more than one prop=val at "
24556e91bba0SGirish Moodalbail "a time.\n%s", use);
24566e91bba0SGirish Moodalbail }
24576e91bba0SGirish Moodalbail }
2458