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 */
216e91bba0SGirish Moodalbail /*
228b88711aSGirish Moodalbail * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*7bc87895SYuri Pankov * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
246e91bba0SGirish Moodalbail */
256e91bba0SGirish Moodalbail #include <arpa/inet.h>
266e91bba0SGirish Moodalbail #include <errno.h>
276e91bba0SGirish Moodalbail #include <getopt.h>
286e91bba0SGirish Moodalbail #include <inet/ip.h>
296e91bba0SGirish Moodalbail #include <inet/iptun.h>
306e91bba0SGirish Moodalbail #include <inet/tunables.h>
316e91bba0SGirish Moodalbail #include <libdladm.h>
326e91bba0SGirish Moodalbail #include <libdliptun.h>
336e91bba0SGirish Moodalbail #include <libdllink.h>
346e91bba0SGirish Moodalbail #include <libinetutil.h>
356e91bba0SGirish Moodalbail #include <libipadm.h>
366e91bba0SGirish Moodalbail #include <locale.h>
376e91bba0SGirish Moodalbail #include <netdb.h>
386e91bba0SGirish Moodalbail #include <netinet/in.h>
396e91bba0SGirish Moodalbail #include <ofmt.h>
406e91bba0SGirish Moodalbail #include <stdarg.h>
416e91bba0SGirish Moodalbail #include <stddef.h>
426e91bba0SGirish Moodalbail #include <stdio.h>
436e91bba0SGirish Moodalbail #include <stdlib.h>
446e91bba0SGirish Moodalbail #include <string.h>
456e91bba0SGirish Moodalbail #include <strings.h>
466e91bba0SGirish Moodalbail #include <sys/stat.h>
476e91bba0SGirish Moodalbail #include <sys/types.h>
486e91bba0SGirish Moodalbail #include <zone.h>
496e91bba0SGirish Moodalbail
506e91bba0SGirish Moodalbail #define STR_UNKNOWN_VAL "?"
516e91bba0SGirish Moodalbail #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
526e91bba0SGirish Moodalbail LIFC_UNDER_IPMP)
536e91bba0SGirish Moodalbail
546e91bba0SGirish Moodalbail typedef void cmdfunc_t(int, char **, const char *);
556e91bba0SGirish Moodalbail static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
566e91bba0SGirish Moodalbail static cmdfunc_t do_show_if;
578887b57dSGirish Moodalbail static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
586e91bba0SGirish Moodalbail static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
596e91bba0SGirish Moodalbail static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
606e91bba0SGirish Moodalbail static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
616e91bba0SGirish Moodalbail static cmdfunc_t do_enable_addr, do_disable_addr;
626e91bba0SGirish Moodalbail static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
636e91bba0SGirish Moodalbail
646e91bba0SGirish Moodalbail typedef struct cmd {
656e91bba0SGirish Moodalbail char *c_name;
666e91bba0SGirish Moodalbail cmdfunc_t *c_fn;
676e91bba0SGirish Moodalbail const char *c_usage;
686e91bba0SGirish Moodalbail } cmd_t;
696e91bba0SGirish Moodalbail
706e91bba0SGirish Moodalbail static cmd_t cmds[] = {
716e91bba0SGirish Moodalbail /* interface management related sub-commands */
726e91bba0SGirish Moodalbail { "create-if", do_create_if, "\tcreate-if\t[-t] <interface>" },
736e91bba0SGirish Moodalbail { "disable-if", do_disable_if, "\tdisable-if\t-t <interface>" },
746e91bba0SGirish Moodalbail { "enable-if", do_enable_if, "\tenable-if\t-t <interface>" },
756e91bba0SGirish Moodalbail { "delete-if", do_delete_if, "\tdelete-if\t<interface>" },
766e91bba0SGirish Moodalbail { "show-if", do_show_if,
776e91bba0SGirish Moodalbail "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
786e91bba0SGirish Moodalbail { "set-ifprop", do_set_ifprop,
796e91bba0SGirish Moodalbail "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
806e91bba0SGirish Moodalbail "<interface>" },
816e91bba0SGirish Moodalbail { "reset-ifprop", do_reset_ifprop,
826e91bba0SGirish Moodalbail "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
836e91bba0SGirish Moodalbail { "show-ifprop", do_show_ifprop,
846e91bba0SGirish Moodalbail "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
856e91bba0SGirish Moodalbail "\t\t\t[-m <protocol>] [interface]\n" },
866e91bba0SGirish Moodalbail
876e91bba0SGirish Moodalbail /* address management related sub-commands */
886e91bba0SGirish Moodalbail { "create-addr", do_create_addr,
89*7bc87895SYuri Pankov "\tcreate-addr\t[-t] -T static [-d] "
90*7bc87895SYuri Pankov "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
91*7bc87895SYuri Pankov "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever] <addrobj>\n"
92*7bc87895SYuri Pankov "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
93*7bc87895SYuri Pankov "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
946e91bba0SGirish Moodalbail { "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>" },
956e91bba0SGirish Moodalbail { "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>" },
966e91bba0SGirish Moodalbail { "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
976e91bba0SGirish Moodalbail { "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>" },
986e91bba0SGirish Moodalbail { "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
996e91bba0SGirish Moodalbail { "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
1006e91bba0SGirish Moodalbail { "show-addr", do_show_addr,
1016e91bba0SGirish Moodalbail "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n" },
1026e91bba0SGirish Moodalbail { "set-addrprop", do_set_addrprop,
1036e91bba0SGirish Moodalbail "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
1046e91bba0SGirish Moodalbail { "reset-addrprop", do_reset_addrprop,
1056e91bba0SGirish Moodalbail "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
1066e91bba0SGirish Moodalbail { "show-addrprop", do_show_addrprop,
1076e91bba0SGirish Moodalbail "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
1086e91bba0SGirish Moodalbail "<addrobj>\n" },
1096e91bba0SGirish Moodalbail
1106e91bba0SGirish Moodalbail /* protocol properties related sub-commands */
1116e91bba0SGirish Moodalbail { "set-prop", do_set_prop,
1126e91bba0SGirish Moodalbail "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
1136e91bba0SGirish Moodalbail { "reset-prop", do_reset_prop,
1146e91bba0SGirish Moodalbail "\treset-prop\t[-t] -p <prop> <protocol>" },
1156e91bba0SGirish Moodalbail { "show-prop", do_show_prop,
1166e91bba0SGirish Moodalbail "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
1178887b57dSGirish Moodalbail " [protocol]" }
1186e91bba0SGirish Moodalbail };
1196e91bba0SGirish Moodalbail
1206e91bba0SGirish Moodalbail static const struct option if_longopts[] = {
1216e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1226e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1236e91bba0SGirish Moodalbail };
1246e91bba0SGirish Moodalbail
1256e91bba0SGirish Moodalbail static const struct option show_prop_longopts[] = {
1266e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'c' },
1276e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1286e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
1296e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1306e91bba0SGirish Moodalbail };
1316e91bba0SGirish Moodalbail
1326e91bba0SGirish Moodalbail static const struct option show_ifprop_longopts[] = {
1336e91bba0SGirish Moodalbail {"module", required_argument, 0, 'm' },
1346e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'c' },
1356e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1366e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
1376e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1386e91bba0SGirish Moodalbail };
1396e91bba0SGirish Moodalbail
1406e91bba0SGirish Moodalbail static const struct option set_prop_longopts[] = {
1416e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1426e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1436e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1446e91bba0SGirish Moodalbail };
1456e91bba0SGirish Moodalbail
1466e91bba0SGirish Moodalbail static const struct option set_ifprop_longopts[] = {
1476e91bba0SGirish Moodalbail {"module", required_argument, 0, 'm' },
1486e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1496e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1506e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1516e91bba0SGirish Moodalbail };
1526e91bba0SGirish Moodalbail
1536e91bba0SGirish Moodalbail static const struct option addr_misc_longopts[] = {
1546e91bba0SGirish Moodalbail {"inform", no_argument, 0, 'i' },
1556e91bba0SGirish Moodalbail {"release", no_argument, 0, 'r' },
1566e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1576e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1586e91bba0SGirish Moodalbail };
1596e91bba0SGirish Moodalbail
1606e91bba0SGirish Moodalbail static const struct option addr_longopts[] = {
1616e91bba0SGirish Moodalbail {"address", required_argument, 0, 'a' },
1626e91bba0SGirish Moodalbail {"down", no_argument, 0, 'd' },
1636e91bba0SGirish Moodalbail {"interface-id", required_argument, 0, 'i' },
1646e91bba0SGirish Moodalbail {"prop", required_argument, 0, 'p' },
1656e91bba0SGirish Moodalbail {"temporary", no_argument, 0, 't' },
1666e91bba0SGirish Moodalbail {"type", required_argument, 0, 'T' },
1676e91bba0SGirish Moodalbail {"wait", required_argument, 0, 'w' },
1686e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1696e91bba0SGirish Moodalbail };
1706e91bba0SGirish Moodalbail
1716e91bba0SGirish Moodalbail static const struct option show_addr_longopts[] = {
1726e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'p' },
1736e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
1746e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1756e91bba0SGirish Moodalbail };
1766e91bba0SGirish Moodalbail
1776e91bba0SGirish Moodalbail static const struct option show_if_longopts[] = {
1786e91bba0SGirish Moodalbail {"parsable", no_argument, 0, 'p' },
1796e91bba0SGirish Moodalbail {"output", required_argument, 0, 'o' },
1806e91bba0SGirish Moodalbail { 0, 0, 0, 0 }
1816e91bba0SGirish Moodalbail };
1826e91bba0SGirish Moodalbail
1836e91bba0SGirish Moodalbail /* callback functions to print show-* subcommands output */
1846e91bba0SGirish Moodalbail static ofmt_cb_t print_prop_cb;
1856e91bba0SGirish Moodalbail static ofmt_cb_t print_sa_cb;
1866e91bba0SGirish Moodalbail static ofmt_cb_t print_si_cb;
1876e91bba0SGirish Moodalbail
1886e91bba0SGirish Moodalbail /* structures for 'ipadm show-*' subcommands */
1896e91bba0SGirish Moodalbail typedef enum {
1906e91bba0SGirish Moodalbail IPADM_PROPFIELD_IFNAME,
1916e91bba0SGirish Moodalbail IPADM_PROPFIELD_PROTO,
1926e91bba0SGirish Moodalbail IPADM_PROPFIELD_ADDROBJ,
1936e91bba0SGirish Moodalbail IPADM_PROPFIELD_PROPERTY,
1946e91bba0SGirish Moodalbail IPADM_PROPFIELD_PERM,
1956e91bba0SGirish Moodalbail IPADM_PROPFIELD_CURRENT,
1966e91bba0SGirish Moodalbail IPADM_PROPFIELD_PERSISTENT,
1976e91bba0SGirish Moodalbail IPADM_PROPFIELD_DEFAULT,
1986e91bba0SGirish Moodalbail IPADM_PROPFIELD_POSSIBLE
1996e91bba0SGirish Moodalbail } ipadm_propfield_index_t;
2006e91bba0SGirish Moodalbail
2016e91bba0SGirish Moodalbail static ofmt_field_t intfprop_fields[] = {
2026e91bba0SGirish Moodalbail /* name, field width, index, callback */
2036e91bba0SGirish Moodalbail { "IFNAME", 12, IPADM_PROPFIELD_IFNAME, print_prop_cb},
2046e91bba0SGirish Moodalbail { "PROPERTY", 16, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
2056e91bba0SGirish Moodalbail { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
2066e91bba0SGirish Moodalbail { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
2076e91bba0SGirish Moodalbail { "CURRENT", 11, IPADM_PROPFIELD_CURRENT, print_prop_cb},
2086e91bba0SGirish Moodalbail { "PERSISTENT", 11, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
2096e91bba0SGirish Moodalbail { "DEFAULT", 11, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
2106e91bba0SGirish Moodalbail { "POSSIBLE", 16, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
2116e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
2126e91bba0SGirish Moodalbail };
2136e91bba0SGirish Moodalbail
2146e91bba0SGirish Moodalbail
2156e91bba0SGirish Moodalbail static ofmt_field_t modprop_fields[] = {
2166e91bba0SGirish Moodalbail /* name, field width, index, callback */
2176e91bba0SGirish Moodalbail { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
2186e91bba0SGirish Moodalbail { "PROPERTY", 22, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
2196e91bba0SGirish Moodalbail { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
2206e91bba0SGirish Moodalbail { "CURRENT", 13, IPADM_PROPFIELD_CURRENT, print_prop_cb},
2216e91bba0SGirish Moodalbail { "PERSISTENT", 13, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
2226e91bba0SGirish Moodalbail { "DEFAULT", 13, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
2236e91bba0SGirish Moodalbail { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
2246e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
2256e91bba0SGirish Moodalbail };
2266e91bba0SGirish Moodalbail
2276e91bba0SGirish Moodalbail static ofmt_field_t addrprop_fields[] = {
2286e91bba0SGirish Moodalbail /* name, field width, index, callback */
2296e91bba0SGirish Moodalbail { "ADDROBJ", 18, IPADM_PROPFIELD_ADDROBJ, print_prop_cb},
2306e91bba0SGirish Moodalbail { "PROPERTY", 11, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
2316e91bba0SGirish Moodalbail { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
2326e91bba0SGirish Moodalbail { "CURRENT", 16, IPADM_PROPFIELD_CURRENT, print_prop_cb},
2336e91bba0SGirish Moodalbail { "PERSISTENT", 16, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
2346e91bba0SGirish Moodalbail { "DEFAULT", 16, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
2356e91bba0SGirish Moodalbail { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
2366e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
2376e91bba0SGirish Moodalbail };
2386e91bba0SGirish Moodalbail
2396e91bba0SGirish Moodalbail typedef struct show_prop_state {
2406e91bba0SGirish Moodalbail char sps_ifname[LIFNAMSIZ];
2416e91bba0SGirish Moodalbail char sps_aobjname[IPADM_AOBJSIZ];
2426e91bba0SGirish Moodalbail const char *sps_pname;
2436e91bba0SGirish Moodalbail uint_t sps_proto;
2446e91bba0SGirish Moodalbail char *sps_propval;
2456e91bba0SGirish Moodalbail nvlist_t *sps_proplist;
2466e91bba0SGirish Moodalbail boolean_t sps_parsable;
2476e91bba0SGirish Moodalbail boolean_t sps_addrprop;
2486e91bba0SGirish Moodalbail boolean_t sps_ifprop;
2496e91bba0SGirish Moodalbail boolean_t sps_modprop;
2506e91bba0SGirish Moodalbail ipadm_status_t sps_status;
2516e91bba0SGirish Moodalbail ipadm_status_t sps_retstatus;
2526e91bba0SGirish Moodalbail ofmt_handle_t sps_ofmt;
2536e91bba0SGirish Moodalbail } show_prop_state_t;
2546e91bba0SGirish Moodalbail
2556e91bba0SGirish Moodalbail typedef struct show_addr_state {
2566e91bba0SGirish Moodalbail boolean_t sa_parsable;
2576e91bba0SGirish Moodalbail boolean_t sa_persist;
2586e91bba0SGirish Moodalbail ofmt_handle_t sa_ofmt;
2596e91bba0SGirish Moodalbail } show_addr_state_t;
2606e91bba0SGirish Moodalbail
2616e91bba0SGirish Moodalbail typedef struct show_if_state {
2626e91bba0SGirish Moodalbail boolean_t si_parsable;
2636e91bba0SGirish Moodalbail ofmt_handle_t si_ofmt;
2646e91bba0SGirish Moodalbail } show_if_state_t;
2656e91bba0SGirish Moodalbail
2666e91bba0SGirish Moodalbail typedef struct show_addr_args_s {
2676e91bba0SGirish Moodalbail show_addr_state_t *sa_state;
2686e91bba0SGirish Moodalbail ipadm_addr_info_t *sa_info;
2696e91bba0SGirish Moodalbail } show_addr_args_t;
2706e91bba0SGirish Moodalbail
2716e91bba0SGirish Moodalbail typedef struct show_if_args_s {
2726e91bba0SGirish Moodalbail show_if_state_t *si_state;
2736e91bba0SGirish Moodalbail ipadm_if_info_t *si_info;
2746e91bba0SGirish Moodalbail } show_if_args_t;
2756e91bba0SGirish Moodalbail
2766e91bba0SGirish Moodalbail typedef enum {
2776e91bba0SGirish Moodalbail SA_ADDROBJ,
2786e91bba0SGirish Moodalbail SA_TYPE,
2796e91bba0SGirish Moodalbail SA_STATE,
2806e91bba0SGirish Moodalbail SA_CURRENT,
2816e91bba0SGirish Moodalbail SA_PERSISTENT,
2826e91bba0SGirish Moodalbail SA_ADDR
2836e91bba0SGirish Moodalbail } sa_field_index_t;
2846e91bba0SGirish Moodalbail
2856e91bba0SGirish Moodalbail typedef enum {
2866e91bba0SGirish Moodalbail SI_IFNAME,
2876e91bba0SGirish Moodalbail SI_STATE,
2886e91bba0SGirish Moodalbail SI_CURRENT,
2896e91bba0SGirish Moodalbail SI_PERSISTENT
2906e91bba0SGirish Moodalbail } si_field_index_t;
2916e91bba0SGirish Moodalbail
2926e91bba0SGirish Moodalbail static ofmt_field_t show_addr_fields[] = {
2936e91bba0SGirish Moodalbail /* name, field width, id, callback */
2946e91bba0SGirish Moodalbail { "ADDROBJ", 18, SA_ADDROBJ, print_sa_cb},
2956e91bba0SGirish Moodalbail { "TYPE", 9, SA_TYPE, print_sa_cb},
2966e91bba0SGirish Moodalbail { "STATE", 13, SA_STATE, print_sa_cb},
2976e91bba0SGirish Moodalbail { "CURRENT", 8, SA_CURRENT, print_sa_cb},
2986e91bba0SGirish Moodalbail { "PERSISTENT", 11, SA_PERSISTENT, print_sa_cb},
2996e91bba0SGirish Moodalbail { "ADDR", 46, SA_ADDR, print_sa_cb},
3006e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
3016e91bba0SGirish Moodalbail };
3026e91bba0SGirish Moodalbail
3036e91bba0SGirish Moodalbail static ofmt_field_t show_if_fields[] = {
3046e91bba0SGirish Moodalbail /* name, field width, id, callback */
3056e91bba0SGirish Moodalbail { "IFNAME", 11, SI_IFNAME, print_si_cb},
3066e91bba0SGirish Moodalbail { "STATE", 9, SI_STATE, print_si_cb},
307550b6e40SSowmini Varadhan { "CURRENT", 13, SI_CURRENT, print_si_cb},
3086e91bba0SGirish Moodalbail { "PERSISTENT", 11, SI_PERSISTENT, print_si_cb},
3096e91bba0SGirish Moodalbail { NULL, 0, 0, NULL}
3106e91bba0SGirish Moodalbail };
3116e91bba0SGirish Moodalbail
3126e91bba0SGirish Moodalbail #define IPADM_ALL_BITS ((uint_t)-1)
3136e91bba0SGirish Moodalbail typedef struct intf_mask {
3146e91bba0SGirish Moodalbail char *name;
3156e91bba0SGirish Moodalbail uint64_t bits;
3166e91bba0SGirish Moodalbail uint64_t mask;
3176e91bba0SGirish Moodalbail } fmask_t;
3186e91bba0SGirish Moodalbail
3196e91bba0SGirish Moodalbail /*
3206e91bba0SGirish Moodalbail * Handle to libipadm. Opened in main() before the sub-command specific
3216e91bba0SGirish Moodalbail * function is called and is closed before the program exits.
3226e91bba0SGirish Moodalbail */
3236e91bba0SGirish Moodalbail ipadm_handle_t iph = NULL;
3246e91bba0SGirish Moodalbail
3256e91bba0SGirish Moodalbail /*
3266e91bba0SGirish Moodalbail * Opaque ipadm address object. Used by all the address management subcommands.
3276e91bba0SGirish Moodalbail */
3286e91bba0SGirish Moodalbail ipadm_addrobj_t ipaddr = NULL;
3296e91bba0SGirish Moodalbail
3306e91bba0SGirish Moodalbail static char *progname;
3316e91bba0SGirish Moodalbail
3326e91bba0SGirish Moodalbail static void die(const char *, ...);
3336e91bba0SGirish Moodalbail static void die_opterr(int, int, const char *);
3346e91bba0SGirish Moodalbail static void warn_ipadmerr(ipadm_status_t, const char *, ...);
3356e91bba0SGirish Moodalbail static void ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
3366e91bba0SGirish Moodalbail static void ipadm_check_propstr(const char *, boolean_t, const char *);
3376e91bba0SGirish Moodalbail static void process_misc_addrargs(int, char **, const char *, int *,
3386e91bba0SGirish Moodalbail uint32_t *);
3396e91bba0SGirish Moodalbail
3406e91bba0SGirish Moodalbail static void
usage(void)3416e91bba0SGirish Moodalbail usage(void)
3426e91bba0SGirish Moodalbail {
3436e91bba0SGirish Moodalbail int i;
3446e91bba0SGirish Moodalbail cmd_t *cmdp;
3456e91bba0SGirish Moodalbail
3466e91bba0SGirish Moodalbail (void) fprintf(stderr,
3476e91bba0SGirish Moodalbail gettext("usage: ipadm <subcommand> <args> ...\n"));
3486e91bba0SGirish Moodalbail for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
3496e91bba0SGirish Moodalbail cmdp = &cmds[i];
3506e91bba0SGirish Moodalbail if (cmdp->c_usage != NULL)
3516e91bba0SGirish Moodalbail (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
3526e91bba0SGirish Moodalbail }
3536e91bba0SGirish Moodalbail
3546e91bba0SGirish Moodalbail ipadm_destroy_addrobj(ipaddr);
3556e91bba0SGirish Moodalbail ipadm_close(iph);
3566e91bba0SGirish Moodalbail exit(1);
3576e91bba0SGirish Moodalbail }
3586e91bba0SGirish Moodalbail
3596e91bba0SGirish Moodalbail int
main(int argc,char * argv[])3606e91bba0SGirish Moodalbail main(int argc, char *argv[])
3616e91bba0SGirish Moodalbail {
3626e91bba0SGirish Moodalbail int i;
3636e91bba0SGirish Moodalbail cmd_t *cmdp;
3646e91bba0SGirish Moodalbail ipadm_status_t status;
3656e91bba0SGirish Moodalbail
3666e91bba0SGirish Moodalbail (void) setlocale(LC_ALL, "");
3676e91bba0SGirish Moodalbail (void) textdomain(TEXT_DOMAIN);
3686e91bba0SGirish Moodalbail
3696e91bba0SGirish Moodalbail if ((progname = strrchr(argv[0], '/')) == NULL)
3706e91bba0SGirish Moodalbail progname = argv[0];
3716e91bba0SGirish Moodalbail else
3726e91bba0SGirish Moodalbail progname++;
3736e91bba0SGirish Moodalbail
3746e91bba0SGirish Moodalbail if (argc < 2)
3756e91bba0SGirish Moodalbail usage();
3766e91bba0SGirish Moodalbail
3776e91bba0SGirish Moodalbail status = ipadm_open(&iph, 0);
3786e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
3796e91bba0SGirish Moodalbail die("Could not open handle to library - %s",
3806e91bba0SGirish Moodalbail ipadm_status2str(status));
3816e91bba0SGirish Moodalbail }
3826e91bba0SGirish Moodalbail
3836e91bba0SGirish Moodalbail for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
3846e91bba0SGirish Moodalbail cmdp = &cmds[i];
3856e91bba0SGirish Moodalbail if (strcmp(argv[1], cmdp->c_name) == 0) {
3866e91bba0SGirish Moodalbail cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
3876e91bba0SGirish Moodalbail ipadm_destroy_addrobj(ipaddr);
3886e91bba0SGirish Moodalbail ipadm_close(iph);
3896e91bba0SGirish Moodalbail exit(0);
3906e91bba0SGirish Moodalbail }
3916e91bba0SGirish Moodalbail }
3926e91bba0SGirish Moodalbail
3936e91bba0SGirish Moodalbail (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
3946e91bba0SGirish Moodalbail progname, argv[1]);
3956e91bba0SGirish Moodalbail usage();
3966e91bba0SGirish Moodalbail
3976e91bba0SGirish Moodalbail return (0);
3986e91bba0SGirish Moodalbail }
3996e91bba0SGirish Moodalbail
4006e91bba0SGirish Moodalbail /*
4016e91bba0SGirish Moodalbail * Create an IP interface for which no saved configuration exists in the
4026e91bba0SGirish Moodalbail * persistent store.
4036e91bba0SGirish Moodalbail */
4046e91bba0SGirish Moodalbail static void
do_create_if(int argc,char * argv[],const char * use)4056e91bba0SGirish Moodalbail do_create_if(int argc, char *argv[], const char *use)
4066e91bba0SGirish Moodalbail {
4076e91bba0SGirish Moodalbail ipadm_status_t status;
4086e91bba0SGirish Moodalbail int option;
4096e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
4106e91bba0SGirish Moodalbail
4116e91bba0SGirish Moodalbail opterr = 0;
4126e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":t", if_longopts,
4136e91bba0SGirish Moodalbail NULL)) != -1) {
4146e91bba0SGirish Moodalbail switch (option) {
4156e91bba0SGirish Moodalbail case 't':
4166e91bba0SGirish Moodalbail /*
4176e91bba0SGirish Moodalbail * "ifconfig" mode - plumb interface, but do not
4186e91bba0SGirish Moodalbail * restore settings that may exist in db.
4196e91bba0SGirish Moodalbail */
4206e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
4216e91bba0SGirish Moodalbail break;
4226e91bba0SGirish Moodalbail default:
4236e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
4246e91bba0SGirish Moodalbail }
4256e91bba0SGirish Moodalbail }
4266e91bba0SGirish Moodalbail if (optind != (argc - 1))
4276e91bba0SGirish Moodalbail die("Usage: %s", use);
4286e91bba0SGirish Moodalbail status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
4296e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
4306e91bba0SGirish Moodalbail die("Could not create %s : %s",
4316e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
4326e91bba0SGirish Moodalbail }
4336e91bba0SGirish Moodalbail }
4346e91bba0SGirish Moodalbail
4356e91bba0SGirish Moodalbail /*
4366e91bba0SGirish Moodalbail * Enable an IP interface based on the persistent configuration for
4376e91bba0SGirish Moodalbail * that interface.
4386e91bba0SGirish Moodalbail */
4396e91bba0SGirish Moodalbail static void
do_enable_if(int argc,char * argv[],const char * use)4406e91bba0SGirish Moodalbail do_enable_if(int argc, char *argv[], const char *use)
4416e91bba0SGirish Moodalbail {
4426e91bba0SGirish Moodalbail ipadm_status_t status;
4436e91bba0SGirish Moodalbail int index;
4446e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
4456e91bba0SGirish Moodalbail
4466e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
4476e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
4486e91bba0SGirish Moodalbail die("persistent operation not supported for enable-if");
4496e91bba0SGirish Moodalbail status = ipadm_enable_if(iph, argv[index], flags);
4506e91bba0SGirish Moodalbail if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
4516e91bba0SGirish Moodalbail warn_ipadmerr(status, "");
4526e91bba0SGirish Moodalbail } else if (status != IPADM_SUCCESS) {
4536e91bba0SGirish Moodalbail die("Could not enable %s : %s",
4546e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
4556e91bba0SGirish Moodalbail }
4566e91bba0SGirish Moodalbail }
4576e91bba0SGirish Moodalbail
4586e91bba0SGirish Moodalbail /*
4596e91bba0SGirish Moodalbail * Remove an IP interface from both active and persistent configuration.
4606e91bba0SGirish Moodalbail */
4616e91bba0SGirish Moodalbail static void
do_delete_if(int argc,char * argv[],const char * use)4626e91bba0SGirish Moodalbail do_delete_if(int argc, char *argv[], const char *use)
4636e91bba0SGirish Moodalbail {
4646e91bba0SGirish Moodalbail ipadm_status_t status;
4656e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
4666e91bba0SGirish Moodalbail
4676e91bba0SGirish Moodalbail if (argc != 2)
4686e91bba0SGirish Moodalbail die("Usage: %s", use);
4696e91bba0SGirish Moodalbail
4706e91bba0SGirish Moodalbail status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
4716e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
4726e91bba0SGirish Moodalbail die("Could not delete %s: %s",
4736e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
4746e91bba0SGirish Moodalbail }
4756e91bba0SGirish Moodalbail }
4766e91bba0SGirish Moodalbail
4776e91bba0SGirish Moodalbail /*
4786e91bba0SGirish Moodalbail * Disable an IP interface by removing it from active configuration.
4796e91bba0SGirish Moodalbail */
4806e91bba0SGirish Moodalbail static void
do_disable_if(int argc,char * argv[],const char * use)4816e91bba0SGirish Moodalbail do_disable_if(int argc, char *argv[], const char *use)
4826e91bba0SGirish Moodalbail {
4836e91bba0SGirish Moodalbail ipadm_status_t status;
4846e91bba0SGirish Moodalbail int index;
4856e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
4866e91bba0SGirish Moodalbail
4876e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
4886e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
4896e91bba0SGirish Moodalbail die("persistent operation not supported for disable-if");
4906e91bba0SGirish Moodalbail status = ipadm_disable_if(iph, argv[index], flags);
4916e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
4926e91bba0SGirish Moodalbail die("Could not disable %s: %s",
4936e91bba0SGirish Moodalbail argv[optind], ipadm_status2str(status));
4946e91bba0SGirish Moodalbail }
4956e91bba0SGirish Moodalbail }
4966e91bba0SGirish Moodalbail
4976e91bba0SGirish Moodalbail /*
4986e91bba0SGirish Moodalbail * called in from print_prop_cb() and does the job of printing each
4996e91bba0SGirish Moodalbail * individual column in the 'ipadm show-*prop' output.
5006e91bba0SGirish Moodalbail */
5016e91bba0SGirish Moodalbail static void
print_prop(show_prop_state_t * statep,uint_t flags,char * buf,size_t bufsize)5026e91bba0SGirish Moodalbail print_prop(show_prop_state_t *statep, uint_t flags, char *buf, size_t bufsize)
5036e91bba0SGirish Moodalbail {
5046e91bba0SGirish Moodalbail const char *prop_name = statep->sps_pname;
5056e91bba0SGirish Moodalbail char *ifname = statep->sps_ifname;
5066e91bba0SGirish Moodalbail char *propval = statep->sps_propval;
5076e91bba0SGirish Moodalbail uint_t proto = statep->sps_proto;
5086e91bba0SGirish Moodalbail size_t propsize = MAXPROPVALLEN;
5096e91bba0SGirish Moodalbail char *object;
5106e91bba0SGirish Moodalbail ipadm_status_t status;
5116e91bba0SGirish Moodalbail
5126e91bba0SGirish Moodalbail if (statep->sps_ifprop) {
5136e91bba0SGirish Moodalbail status = ipadm_get_ifprop(iph, ifname, prop_name, propval,
5146e91bba0SGirish Moodalbail &propsize, proto, flags);
5156e91bba0SGirish Moodalbail object = ifname;
5166e91bba0SGirish Moodalbail } else if (statep->sps_modprop) {
5176e91bba0SGirish Moodalbail status = ipadm_get_prop(iph, prop_name, propval, &propsize,
5186e91bba0SGirish Moodalbail proto, flags);
5196e91bba0SGirish Moodalbail object = ipadm_proto2str(proto);
5206e91bba0SGirish Moodalbail } else {
5216e91bba0SGirish Moodalbail status = ipadm_get_addrprop(iph, prop_name, propval, &propsize,
5226e91bba0SGirish Moodalbail statep->sps_aobjname, flags);
5236e91bba0SGirish Moodalbail object = statep->sps_aobjname;
5246e91bba0SGirish Moodalbail }
5256e91bba0SGirish Moodalbail
5266e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
5276e91bba0SGirish Moodalbail if (status == IPADM_PROP_UNKNOWN ||
5286e91bba0SGirish Moodalbail status == IPADM_INVALID_ARG) {
5296e91bba0SGirish Moodalbail warn_ipadmerr(status, "cannot get property '%s' for "
5306e91bba0SGirish Moodalbail "'%s'", prop_name, object);
5316e91bba0SGirish Moodalbail } else if (status == IPADM_NOTSUP) {
5326e91bba0SGirish Moodalbail warn_ipadmerr(status, "'%s'", object);
5336e91bba0SGirish Moodalbail } else if (status == IPADM_NOTFOUND) {
5346e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST) {
5356e91bba0SGirish Moodalbail propval[0] = '\0';
5366e91bba0SGirish Moodalbail goto cont;
5376e91bba0SGirish Moodalbail } else {
5386e91bba0SGirish Moodalbail warn_ipadmerr(status, "no such object '%s'",
5396e91bba0SGirish Moodalbail object);
5406e91bba0SGirish Moodalbail }
5416e91bba0SGirish Moodalbail } else if (status == IPADM_ENXIO) {
5426e91bba0SGirish Moodalbail /* the interface is probably disabled */
5436e91bba0SGirish Moodalbail propval[0] = '\0';
5446e91bba0SGirish Moodalbail goto cont;
5456e91bba0SGirish Moodalbail }
5466e91bba0SGirish Moodalbail statep->sps_status = status;
5476e91bba0SGirish Moodalbail statep->sps_retstatus = status;
5486e91bba0SGirish Moodalbail return;
5496e91bba0SGirish Moodalbail }
5506e91bba0SGirish Moodalbail cont:
5516e91bba0SGirish Moodalbail statep->sps_status = IPADM_SUCCESS;
5526e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", propval);
5536e91bba0SGirish Moodalbail }
5546e91bba0SGirish Moodalbail
5556e91bba0SGirish Moodalbail /*
5566e91bba0SGirish Moodalbail * callback function which displays output for set-prop, set-ifprop and
5576e91bba0SGirish Moodalbail * set-addrprop subcommands.
5586e91bba0SGirish Moodalbail */
5596e91bba0SGirish Moodalbail static boolean_t
print_prop_cb(ofmt_arg_t * ofarg,char * buf,size_t bufsize)5606e91bba0SGirish Moodalbail print_prop_cb(ofmt_arg_t *ofarg, char *buf, size_t bufsize)
5616e91bba0SGirish Moodalbail {
5626e91bba0SGirish Moodalbail show_prop_state_t *statep = ofarg->ofmt_cbarg;
5636e91bba0SGirish Moodalbail const char *propname = statep->sps_pname;
5646e91bba0SGirish Moodalbail uint_t proto = statep->sps_proto;
5656e91bba0SGirish Moodalbail boolean_t cont = _B_TRUE;
5666e91bba0SGirish Moodalbail
5676e91bba0SGirish Moodalbail /*
5686e91bba0SGirish Moodalbail * Fail retrieving remaining fields, if you fail
5696e91bba0SGirish Moodalbail * to retrieve a field.
5706e91bba0SGirish Moodalbail */
5716e91bba0SGirish Moodalbail if (statep->sps_status != IPADM_SUCCESS)
5726e91bba0SGirish Moodalbail return (_B_FALSE);
5736e91bba0SGirish Moodalbail
5746e91bba0SGirish Moodalbail switch (ofarg->ofmt_id) {
5756e91bba0SGirish Moodalbail case IPADM_PROPFIELD_IFNAME:
5766e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", statep->sps_ifname);
5776e91bba0SGirish Moodalbail break;
5786e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PROTO:
5796e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", ipadm_proto2str(proto));
5806e91bba0SGirish Moodalbail break;
5816e91bba0SGirish Moodalbail case IPADM_PROPFIELD_ADDROBJ:
5826e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", statep->sps_aobjname);
5836e91bba0SGirish Moodalbail break;
5846e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PROPERTY:
5856e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", propname);
5866e91bba0SGirish Moodalbail break;
5876e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PERM:
5886e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_PERM, buf, bufsize);
5896e91bba0SGirish Moodalbail break;
5906e91bba0SGirish Moodalbail case IPADM_PROPFIELD_CURRENT:
5916e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_ACTIVE, buf, bufsize);
5926e91bba0SGirish Moodalbail break;
5936e91bba0SGirish Moodalbail case IPADM_PROPFIELD_PERSISTENT:
5946e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_PERSIST, buf, bufsize);
5956e91bba0SGirish Moodalbail break;
5966e91bba0SGirish Moodalbail case IPADM_PROPFIELD_DEFAULT:
5976e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_DEFAULT, buf, bufsize);
5986e91bba0SGirish Moodalbail break;
5996e91bba0SGirish Moodalbail case IPADM_PROPFIELD_POSSIBLE:
6006e91bba0SGirish Moodalbail print_prop(statep, IPADM_OPT_POSSIBLE, buf, bufsize);
6016e91bba0SGirish Moodalbail break;
6026e91bba0SGirish Moodalbail }
6036e91bba0SGirish Moodalbail if (statep->sps_status != IPADM_SUCCESS)
6046e91bba0SGirish Moodalbail cont = _B_FALSE;
6056e91bba0SGirish Moodalbail return (cont);
6066e91bba0SGirish Moodalbail }
6076e91bba0SGirish Moodalbail
6086e91bba0SGirish Moodalbail /*
6096e91bba0SGirish Moodalbail * Callback function called by the property walker (ipadm_walk_prop() or
6106e91bba0SGirish Moodalbail * ipadm_walk_proptbl()), for every matched property. This function in turn
6116e91bba0SGirish Moodalbail * calls ofmt_print() to print property information.
6126e91bba0SGirish Moodalbail */
6136e91bba0SGirish Moodalbail boolean_t
show_property(void * arg,const char * pname,uint_t proto)6146e91bba0SGirish Moodalbail show_property(void *arg, const char *pname, uint_t proto)
6156e91bba0SGirish Moodalbail {
6166e91bba0SGirish Moodalbail show_prop_state_t *statep = arg;
6176e91bba0SGirish Moodalbail
6186e91bba0SGirish Moodalbail statep->sps_pname = pname;
6196e91bba0SGirish Moodalbail statep->sps_proto = proto;
6206e91bba0SGirish Moodalbail statep->sps_status = IPADM_SUCCESS;
6216e91bba0SGirish Moodalbail ofmt_print(statep->sps_ofmt, arg);
6226e91bba0SGirish Moodalbail
6236e91bba0SGirish Moodalbail /*
6246e91bba0SGirish Moodalbail * if an object is not found or operation is not supported then
6256e91bba0SGirish Moodalbail * stop the walker.
6266e91bba0SGirish Moodalbail */
6276e91bba0SGirish Moodalbail if (statep->sps_status == IPADM_NOTFOUND ||
6286e91bba0SGirish Moodalbail statep->sps_status == IPADM_NOTSUP)
6296e91bba0SGirish Moodalbail return (_B_FALSE);
6306e91bba0SGirish Moodalbail return (_B_TRUE);
6316e91bba0SGirish Moodalbail }
6326e91bba0SGirish Moodalbail
6336e91bba0SGirish Moodalbail /*
6346e91bba0SGirish Moodalbail * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
6356e91bba0SGirish Moodalbail * for all the properties for the specified object, relavant information, will
6366e91bba0SGirish Moodalbail * be displayed. Otherwise, for the selected property set, display relevant
6376e91bba0SGirish Moodalbail * information
6386e91bba0SGirish Moodalbail */
6396e91bba0SGirish Moodalbail static void
show_properties(void * arg,int prop_class)6406e91bba0SGirish Moodalbail show_properties(void *arg, int prop_class)
6416e91bba0SGirish Moodalbail {
6426e91bba0SGirish Moodalbail show_prop_state_t *statep = arg;
6436e91bba0SGirish Moodalbail nvlist_t *nvl = statep->sps_proplist;
6446e91bba0SGirish Moodalbail uint_t proto = statep->sps_proto;
6456e91bba0SGirish Moodalbail nvpair_t *curr_nvp;
6466e91bba0SGirish Moodalbail char *buf, *name;
6476e91bba0SGirish Moodalbail ipadm_status_t status;
6486e91bba0SGirish Moodalbail
6496e91bba0SGirish Moodalbail /* allocate sufficient buffer to hold a property value */
6506e91bba0SGirish Moodalbail if ((buf = malloc(MAXPROPVALLEN)) == NULL)
6516e91bba0SGirish Moodalbail die("insufficient memory");
6526e91bba0SGirish Moodalbail statep->sps_propval = buf;
6536e91bba0SGirish Moodalbail
6546e91bba0SGirish Moodalbail /* if no properties were specified, display all the properties */
6556e91bba0SGirish Moodalbail if (nvl == NULL) {
6566e91bba0SGirish Moodalbail (void) ipadm_walk_proptbl(proto, prop_class, show_property,
6576e91bba0SGirish Moodalbail statep);
6586e91bba0SGirish Moodalbail } else {
6596e91bba0SGirish Moodalbail for (curr_nvp = nvlist_next_nvpair(nvl, NULL); curr_nvp;
6606e91bba0SGirish Moodalbail curr_nvp = nvlist_next_nvpair(nvl, curr_nvp)) {
6616e91bba0SGirish Moodalbail name = nvpair_name(curr_nvp);
6626e91bba0SGirish Moodalbail status = ipadm_walk_prop(name, proto, prop_class,
6636e91bba0SGirish Moodalbail show_property, statep);
6646e91bba0SGirish Moodalbail if (status == IPADM_PROP_UNKNOWN)
6656e91bba0SGirish Moodalbail (void) show_property(statep, name, proto);
6666e91bba0SGirish Moodalbail }
6676e91bba0SGirish Moodalbail }
6686e91bba0SGirish Moodalbail
6696e91bba0SGirish Moodalbail free(buf);
6706e91bba0SGirish Moodalbail }
6716e91bba0SGirish Moodalbail
6726e91bba0SGirish Moodalbail /*
6736e91bba0SGirish Moodalbail * Display information for all or specific interface properties, either for a
6746e91bba0SGirish Moodalbail * given interface or for all the interfaces in the system.
6756e91bba0SGirish Moodalbail */
6766e91bba0SGirish Moodalbail static void
do_show_ifprop(int argc,char ** argv,const char * use)6776e91bba0SGirish Moodalbail do_show_ifprop(int argc, char **argv, const char *use)
6786e91bba0SGirish Moodalbail {
6796e91bba0SGirish Moodalbail int option;
6806e91bba0SGirish Moodalbail nvlist_t *proplist = NULL;
6816e91bba0SGirish Moodalbail char *fields_str = NULL;
6826e91bba0SGirish Moodalbail char *ifname;
6836e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
6846e91bba0SGirish Moodalbail ofmt_status_t oferr;
6856e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
6866e91bba0SGirish Moodalbail uint_t proto;
6876e91bba0SGirish Moodalbail boolean_t m_arg = _B_FALSE;
6886e91bba0SGirish Moodalbail char *protostr;
6896e91bba0SGirish Moodalbail ipadm_if_info_t *ifinfo, *ifp;
6906e91bba0SGirish Moodalbail ipadm_status_t status;
6916e91bba0SGirish Moodalbail show_prop_state_t state;
6926e91bba0SGirish Moodalbail
6936e91bba0SGirish Moodalbail opterr = 0;
6946e91bba0SGirish Moodalbail bzero(&state, sizeof (state));
6956e91bba0SGirish Moodalbail state.sps_propval = NULL;
6966e91bba0SGirish Moodalbail state.sps_parsable = _B_FALSE;
6976e91bba0SGirish Moodalbail state.sps_ifprop = _B_TRUE;
6986e91bba0SGirish Moodalbail state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
6996e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:m:co:",
7006e91bba0SGirish Moodalbail show_ifprop_longopts, NULL)) != -1) {
7016e91bba0SGirish Moodalbail switch (option) {
7026e91bba0SGirish Moodalbail case 'p':
7036e91bba0SGirish Moodalbail if (ipadm_str2nvlist(optarg, &proplist,
7046e91bba0SGirish Moodalbail IPADM_NORVAL) != 0)
7056e91bba0SGirish Moodalbail die("invalid interface properties specified");
7066e91bba0SGirish Moodalbail break;
7076e91bba0SGirish Moodalbail case 'c':
7086e91bba0SGirish Moodalbail state.sps_parsable = _B_TRUE;
7096e91bba0SGirish Moodalbail break;
7106e91bba0SGirish Moodalbail case 'o':
7116e91bba0SGirish Moodalbail fields_str = optarg;
7126e91bba0SGirish Moodalbail break;
7136e91bba0SGirish Moodalbail case 'm':
7146e91bba0SGirish Moodalbail if (m_arg)
7156e91bba0SGirish Moodalbail die("cannot specify more than one -m");
7166e91bba0SGirish Moodalbail m_arg = _B_TRUE;
7176e91bba0SGirish Moodalbail protostr = optarg;
7186e91bba0SGirish Moodalbail break;
7196e91bba0SGirish Moodalbail default:
7206e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
7216e91bba0SGirish Moodalbail break;
7226e91bba0SGirish Moodalbail }
7236e91bba0SGirish Moodalbail }
7246e91bba0SGirish Moodalbail
7256e91bba0SGirish Moodalbail if (optind == argc - 1)
7266e91bba0SGirish Moodalbail ifname = argv[optind];
7276e91bba0SGirish Moodalbail else if (optind != argc)
7286e91bba0SGirish Moodalbail die("Usage: %s", use);
7296e91bba0SGirish Moodalbail else
7306e91bba0SGirish Moodalbail ifname = NULL;
7316e91bba0SGirish Moodalbail
7326e91bba0SGirish Moodalbail if (!m_arg)
7336e91bba0SGirish Moodalbail protostr = "ip";
7346e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
7356e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
7366e91bba0SGirish Moodalbail
7376e91bba0SGirish Moodalbail state.sps_proto = proto;
7386e91bba0SGirish Moodalbail state.sps_proplist = proplist;
7396e91bba0SGirish Moodalbail
7406e91bba0SGirish Moodalbail if (state.sps_parsable)
7416e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
7426e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
7436e91bba0SGirish Moodalbail ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
7446e91bba0SGirish Moodalbail state.sps_ofmt = ofmt;
7456e91bba0SGirish Moodalbail
7466e91bba0SGirish Moodalbail /* retrieve interface(s) and print the properties */
7476e91bba0SGirish Moodalbail status = ipadm_if_info(iph, ifname, &ifinfo, 0, LIFC_DEFAULT);
7486e91bba0SGirish Moodalbail if (ifname != NULL && status == IPADM_ENXIO)
7496e91bba0SGirish Moodalbail die("no such object '%s': %s", ifname,
7506e91bba0SGirish Moodalbail ipadm_status2str(status));
7516e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
7526e91bba0SGirish Moodalbail die("Error retrieving interface(s): %s",
7536e91bba0SGirish Moodalbail ipadm_status2str(status));
7546e91bba0SGirish Moodalbail for (ifp = ifinfo; ifp; ifp = ifp->ifi_next) {
7556e91bba0SGirish Moodalbail (void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);
7566e91bba0SGirish Moodalbail state.sps_proto = proto;
7576e91bba0SGirish Moodalbail show_properties(&state, IPADMPROP_CLASS_IF);
7586e91bba0SGirish Moodalbail }
7596e91bba0SGirish Moodalbail if (ifinfo)
7606e91bba0SGirish Moodalbail ipadm_free_if_info(ifinfo);
7616e91bba0SGirish Moodalbail
7626e91bba0SGirish Moodalbail nvlist_free(proplist);
7636e91bba0SGirish Moodalbail ofmt_close(ofmt);
7646e91bba0SGirish Moodalbail
7656e91bba0SGirish Moodalbail if (state.sps_retstatus != IPADM_SUCCESS) {
7666e91bba0SGirish Moodalbail ipadm_close(iph);
7676e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
7686e91bba0SGirish Moodalbail }
7696e91bba0SGirish Moodalbail }
7706e91bba0SGirish Moodalbail
7716e91bba0SGirish Moodalbail /*
7726e91bba0SGirish Moodalbail * set/reset the interface property for a given interface.
7736e91bba0SGirish Moodalbail */
7746e91bba0SGirish Moodalbail static void
set_ifprop(int argc,char ** argv,boolean_t reset,const char * use)7756e91bba0SGirish Moodalbail set_ifprop(int argc, char **argv, boolean_t reset, const char *use)
7766e91bba0SGirish Moodalbail {
7776e91bba0SGirish Moodalbail int option;
7786e91bba0SGirish Moodalbail ipadm_status_t status = IPADM_SUCCESS;
7796e91bba0SGirish Moodalbail boolean_t p_arg = _B_FALSE;
7806e91bba0SGirish Moodalbail boolean_t m_arg = _B_FALSE;
7816e91bba0SGirish Moodalbail char *ifname, *nv, *protostr;
7826e91bba0SGirish Moodalbail char *prop_name, *prop_val;
7836e91bba0SGirish Moodalbail uint_t flags = IPADM_OPT_PERSIST;
7846e91bba0SGirish Moodalbail uint_t proto;
7856e91bba0SGirish Moodalbail
7866e91bba0SGirish Moodalbail opterr = 0;
7876e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":m:p:t",
7886e91bba0SGirish Moodalbail set_ifprop_longopts, NULL)) != -1) {
7896e91bba0SGirish Moodalbail switch (option) {
7906e91bba0SGirish Moodalbail case 'p':
7916e91bba0SGirish Moodalbail if (p_arg)
7926e91bba0SGirish Moodalbail die("-p must be specified once only");
7936e91bba0SGirish Moodalbail p_arg = _B_TRUE;
7946e91bba0SGirish Moodalbail
7956e91bba0SGirish Moodalbail ipadm_check_propstr(optarg, reset, use);
7966e91bba0SGirish Moodalbail nv = optarg;
7976e91bba0SGirish Moodalbail break;
7986e91bba0SGirish Moodalbail case 'm':
7996e91bba0SGirish Moodalbail if (m_arg)
8006e91bba0SGirish Moodalbail die("-m must be specified once only");
8016e91bba0SGirish Moodalbail m_arg = _B_TRUE;
8026e91bba0SGirish Moodalbail protostr = optarg;
8036e91bba0SGirish Moodalbail break;
8046e91bba0SGirish Moodalbail case 't':
8056e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
8066e91bba0SGirish Moodalbail break;
8076e91bba0SGirish Moodalbail default:
8086e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
8096e91bba0SGirish Moodalbail }
8106e91bba0SGirish Moodalbail }
8116e91bba0SGirish Moodalbail
8126e91bba0SGirish Moodalbail if (!m_arg || !p_arg || optind != argc - 1)
8136e91bba0SGirish Moodalbail die("Usage: %s", use);
8146e91bba0SGirish Moodalbail
8156e91bba0SGirish Moodalbail ifname = argv[optind];
8166e91bba0SGirish Moodalbail
8176e91bba0SGirish Moodalbail prop_name = nv;
8186e91bba0SGirish Moodalbail prop_val = strchr(nv, '=');
8196e91bba0SGirish Moodalbail if (prop_val != NULL)
8206e91bba0SGirish Moodalbail *prop_val++ = '\0';
8216e91bba0SGirish Moodalbail
8226e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
8236e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
8246e91bba0SGirish Moodalbail
8256e91bba0SGirish Moodalbail if (reset)
8266e91bba0SGirish Moodalbail flags |= IPADM_OPT_DEFAULT;
8276e91bba0SGirish Moodalbail else
8286e91bba0SGirish Moodalbail flags |= IPADM_OPT_ACTIVE;
8296e91bba0SGirish Moodalbail status = ipadm_set_ifprop(iph, ifname, prop_name, prop_val, proto,
8306e91bba0SGirish Moodalbail flags);
8316e91bba0SGirish Moodalbail
8326e91bba0SGirish Moodalbail done:
8336e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
8346e91bba0SGirish Moodalbail if (reset)
8356e91bba0SGirish Moodalbail die("reset-ifprop: %s: %s",
8366e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
8376e91bba0SGirish Moodalbail else
8386e91bba0SGirish Moodalbail die("set-ifprop: %s: %s",
8396e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
8406e91bba0SGirish Moodalbail }
8416e91bba0SGirish Moodalbail }
8426e91bba0SGirish Moodalbail
8436e91bba0SGirish Moodalbail static void
do_set_ifprop(int argc,char ** argv,const char * use)8446e91bba0SGirish Moodalbail do_set_ifprop(int argc, char **argv, const char *use)
8456e91bba0SGirish Moodalbail {
8466e91bba0SGirish Moodalbail set_ifprop(argc, argv, _B_FALSE, use);
8476e91bba0SGirish Moodalbail }
8486e91bba0SGirish Moodalbail
8496e91bba0SGirish Moodalbail static void
do_reset_ifprop(int argc,char ** argv,const char * use)8506e91bba0SGirish Moodalbail do_reset_ifprop(int argc, char **argv, const char *use)
8516e91bba0SGirish Moodalbail {
8526e91bba0SGirish Moodalbail set_ifprop(argc, argv, _B_TRUE, use);
8536e91bba0SGirish Moodalbail }
8546e91bba0SGirish Moodalbail
8556e91bba0SGirish Moodalbail /*
8566e91bba0SGirish Moodalbail * Display information for all or specific protocol properties, either for a
8576e91bba0SGirish Moodalbail * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
8586e91bba0SGirish Moodalbail */
8596e91bba0SGirish Moodalbail static void
do_show_prop(int argc,char ** argv,const char * use)8606e91bba0SGirish Moodalbail do_show_prop(int argc, char **argv, const char *use)
8616e91bba0SGirish Moodalbail {
8626e91bba0SGirish Moodalbail char option;
8636e91bba0SGirish Moodalbail nvlist_t *proplist = NULL;
8646e91bba0SGirish Moodalbail char *fields_str = NULL;
8656e91bba0SGirish Moodalbail char *protostr;
8666e91bba0SGirish Moodalbail show_prop_state_t state;
8676e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
8686e91bba0SGirish Moodalbail ofmt_status_t oferr;
8696e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
8706e91bba0SGirish Moodalbail uint_t proto;
8716e91bba0SGirish Moodalbail boolean_t p_arg = _B_FALSE;
8726e91bba0SGirish Moodalbail
8736e91bba0SGirish Moodalbail opterr = 0;
8746e91bba0SGirish Moodalbail bzero(&state, sizeof (state));
8756e91bba0SGirish Moodalbail state.sps_propval = NULL;
8766e91bba0SGirish Moodalbail state.sps_parsable = _B_FALSE;
8776e91bba0SGirish Moodalbail state.sps_modprop = _B_TRUE;
8786e91bba0SGirish Moodalbail state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
8796e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:co:", show_prop_longopts,
8806e91bba0SGirish Moodalbail NULL)) != -1) {
8816e91bba0SGirish Moodalbail switch (option) {
8826e91bba0SGirish Moodalbail case 'p':
8836e91bba0SGirish Moodalbail if (p_arg)
8846e91bba0SGirish Moodalbail die("-p must be specified once only");
8856e91bba0SGirish Moodalbail p_arg = _B_TRUE;
8866e91bba0SGirish Moodalbail if (ipadm_str2nvlist(optarg, &proplist,
8876e91bba0SGirish Moodalbail IPADM_NORVAL) != 0)
8886e91bba0SGirish Moodalbail die("invalid protocol properties specified");
8896e91bba0SGirish Moodalbail break;
8906e91bba0SGirish Moodalbail case 'c':
8916e91bba0SGirish Moodalbail state.sps_parsable = _B_TRUE;
8926e91bba0SGirish Moodalbail break;
8936e91bba0SGirish Moodalbail case 'o':
8946e91bba0SGirish Moodalbail fields_str = optarg;
8956e91bba0SGirish Moodalbail break;
8966e91bba0SGirish Moodalbail default:
8976e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
8986e91bba0SGirish Moodalbail break;
8996e91bba0SGirish Moodalbail }
9006e91bba0SGirish Moodalbail }
9016e91bba0SGirish Moodalbail if (optind == argc - 1) {
9026e91bba0SGirish Moodalbail protostr = argv[optind];
9036e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
9046e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
9056e91bba0SGirish Moodalbail state.sps_proto = proto;
9066e91bba0SGirish Moodalbail } else if (optind != argc) {
9076e91bba0SGirish Moodalbail die("Usage: %s", use);
9086e91bba0SGirish Moodalbail } else {
9096e91bba0SGirish Moodalbail if (p_arg)
9106e91bba0SGirish Moodalbail die("protocol must be specified when "
9116e91bba0SGirish Moodalbail "property name is used");
9126e91bba0SGirish Moodalbail state.sps_proto = MOD_PROTO_NONE;
9136e91bba0SGirish Moodalbail }
9146e91bba0SGirish Moodalbail
9156e91bba0SGirish Moodalbail state.sps_proplist = proplist;
9166e91bba0SGirish Moodalbail
9176e91bba0SGirish Moodalbail if (state.sps_parsable)
9186e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
9196e91bba0SGirish Moodalbail else
9206e91bba0SGirish Moodalbail ofmtflags |= OFMT_WRAP;
9216e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
9226e91bba0SGirish Moodalbail ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
9236e91bba0SGirish Moodalbail state.sps_ofmt = ofmt;
9246e91bba0SGirish Moodalbail
9256e91bba0SGirish Moodalbail /* handles all the errors */
9266e91bba0SGirish Moodalbail show_properties(&state, IPADMPROP_CLASS_MODULE);
9276e91bba0SGirish Moodalbail
9286e91bba0SGirish Moodalbail nvlist_free(proplist);
9296e91bba0SGirish Moodalbail ofmt_close(ofmt);
9306e91bba0SGirish Moodalbail
9316e91bba0SGirish Moodalbail if (state.sps_retstatus != IPADM_SUCCESS) {
9326e91bba0SGirish Moodalbail ipadm_close(iph);
9336e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
9346e91bba0SGirish Moodalbail }
9356e91bba0SGirish Moodalbail }
9366e91bba0SGirish Moodalbail
9376e91bba0SGirish Moodalbail /*
9386e91bba0SGirish Moodalbail * Checks to see if there are any modifiers, + or -. If there are modifiers
9396e91bba0SGirish Moodalbail * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
9406e91bba0SGirish Moodalbail */
9416e91bba0SGirish Moodalbail static void
parse_modifiers(const char * pstr,uint_t * flags,const char * use)9428b88711aSGirish Moodalbail parse_modifiers(const char *pstr, uint_t *flags, const char *use)
9436e91bba0SGirish Moodalbail {
9446e91bba0SGirish Moodalbail char *p;
9456e91bba0SGirish Moodalbail
9468b88711aSGirish Moodalbail if ((p = strchr(pstr, '=')) == NULL)
9478b88711aSGirish Moodalbail return;
9486e91bba0SGirish Moodalbail
9498b88711aSGirish Moodalbail if (p == pstr)
9508b88711aSGirish Moodalbail die("Invalid prop=val specified\n%s", use);
9516e91bba0SGirish Moodalbail
9528b88711aSGirish Moodalbail --p;
9538b88711aSGirish Moodalbail if (*p == '+')
9546e91bba0SGirish Moodalbail *flags |= IPADM_OPT_APPEND;
9558b88711aSGirish Moodalbail else if (*p == '-')
9566e91bba0SGirish Moodalbail *flags |= IPADM_OPT_REMOVE;
9576e91bba0SGirish Moodalbail }
9586e91bba0SGirish Moodalbail
9596e91bba0SGirish Moodalbail /*
9606e91bba0SGirish Moodalbail * set/reset the protocol property for a given protocol.
9616e91bba0SGirish Moodalbail */
9626e91bba0SGirish Moodalbail static void
set_prop(int argc,char ** argv,boolean_t reset,const char * use)9636e91bba0SGirish Moodalbail set_prop(int argc, char **argv, boolean_t reset, const char *use)
9646e91bba0SGirish Moodalbail {
9656e91bba0SGirish Moodalbail int option;
9666e91bba0SGirish Moodalbail ipadm_status_t status = IPADM_SUCCESS;
9676e91bba0SGirish Moodalbail char *protostr, *nv, *prop_name, *prop_val;
9686e91bba0SGirish Moodalbail boolean_t p_arg = _B_FALSE;
9696e91bba0SGirish Moodalbail uint_t proto;
9706e91bba0SGirish Moodalbail uint_t flags = IPADM_OPT_PERSIST;
9716e91bba0SGirish Moodalbail
9726e91bba0SGirish Moodalbail opterr = 0;
9736e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:t", set_prop_longopts,
9746e91bba0SGirish Moodalbail NULL)) != -1) {
9756e91bba0SGirish Moodalbail switch (option) {
9766e91bba0SGirish Moodalbail case 'p':
9776e91bba0SGirish Moodalbail if (p_arg)
9786e91bba0SGirish Moodalbail die("-p must be specified once only");
9796e91bba0SGirish Moodalbail p_arg = _B_TRUE;
9806e91bba0SGirish Moodalbail
9816e91bba0SGirish Moodalbail ipadm_check_propstr(optarg, reset, use);
9826e91bba0SGirish Moodalbail nv = optarg;
9836e91bba0SGirish Moodalbail break;
9846e91bba0SGirish Moodalbail case 't':
9856e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
9866e91bba0SGirish Moodalbail break;
9876e91bba0SGirish Moodalbail default:
9886e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
9896e91bba0SGirish Moodalbail }
9906e91bba0SGirish Moodalbail }
9916e91bba0SGirish Moodalbail
9926e91bba0SGirish Moodalbail if (!p_arg || optind != argc - 1)
9936e91bba0SGirish Moodalbail die("Usage: %s", use);
9946e91bba0SGirish Moodalbail
9956e91bba0SGirish Moodalbail parse_modifiers(nv, &flags, use);
9966e91bba0SGirish Moodalbail prop_name = nv;
9976e91bba0SGirish Moodalbail prop_val = strchr(nv, '=');
9986e91bba0SGirish Moodalbail if (prop_val != NULL) {
9996e91bba0SGirish Moodalbail if (flags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))
10006e91bba0SGirish Moodalbail *(prop_val - 1) = '\0';
10016e91bba0SGirish Moodalbail *prop_val++ = '\0';
10026e91bba0SGirish Moodalbail }
10036e91bba0SGirish Moodalbail protostr = argv[optind];
10046e91bba0SGirish Moodalbail if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
10056e91bba0SGirish Moodalbail die("invalid protocol '%s' specified", protostr);
10066e91bba0SGirish Moodalbail
10076e91bba0SGirish Moodalbail if (reset)
10086e91bba0SGirish Moodalbail flags |= IPADM_OPT_DEFAULT;
10096e91bba0SGirish Moodalbail else
10106e91bba0SGirish Moodalbail flags |= IPADM_OPT_ACTIVE;
10116e91bba0SGirish Moodalbail status = ipadm_set_prop(iph, prop_name, prop_val, proto, flags);
10126e91bba0SGirish Moodalbail done:
10136e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
10146e91bba0SGirish Moodalbail if (reset)
10156e91bba0SGirish Moodalbail die("reset-prop: %s: %s",
10166e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
10176e91bba0SGirish Moodalbail else
10186e91bba0SGirish Moodalbail die("set-prop: %s: %s",
10196e91bba0SGirish Moodalbail prop_name, ipadm_status2str(status));
10206e91bba0SGirish Moodalbail }
10216e91bba0SGirish Moodalbail }
10226e91bba0SGirish Moodalbail
10236e91bba0SGirish Moodalbail static void
do_set_prop(int argc,char ** argv,const char * use)10246e91bba0SGirish Moodalbail do_set_prop(int argc, char **argv, const char *use)
10256e91bba0SGirish Moodalbail {
10266e91bba0SGirish Moodalbail set_prop(argc, argv, _B_FALSE, use);
10276e91bba0SGirish Moodalbail }
10286e91bba0SGirish Moodalbail
10296e91bba0SGirish Moodalbail static void
do_reset_prop(int argc,char ** argv,const char * use)10306e91bba0SGirish Moodalbail do_reset_prop(int argc, char **argv, const char *use)
10316e91bba0SGirish Moodalbail {
10326e91bba0SGirish Moodalbail set_prop(argc, argv, _B_TRUE, use);
10336e91bba0SGirish Moodalbail }
10346e91bba0SGirish Moodalbail
10356e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
10366e91bba0SGirish Moodalbail static void
warn(const char * format,...)10376e91bba0SGirish Moodalbail warn(const char *format, ...)
10386e91bba0SGirish Moodalbail {
10396e91bba0SGirish Moodalbail va_list alist;
10406e91bba0SGirish Moodalbail
10416e91bba0SGirish Moodalbail format = gettext(format);
10426e91bba0SGirish Moodalbail (void) fprintf(stderr, gettext("%s: warning: "), progname);
10436e91bba0SGirish Moodalbail
10446e91bba0SGirish Moodalbail va_start(alist, format);
10456e91bba0SGirish Moodalbail (void) vfprintf(stderr, format, alist);
10466e91bba0SGirish Moodalbail va_end(alist);
10476e91bba0SGirish Moodalbail
10486e91bba0SGirish Moodalbail (void) fprintf(stderr, "\n");
10496e91bba0SGirish Moodalbail }
10506e91bba0SGirish Moodalbail
10516e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
10526e91bba0SGirish Moodalbail static void
die(const char * format,...)10536e91bba0SGirish Moodalbail die(const char *format, ...)
10546e91bba0SGirish Moodalbail {
10556e91bba0SGirish Moodalbail va_list alist;
10566e91bba0SGirish Moodalbail
10576e91bba0SGirish Moodalbail format = gettext(format);
10586e91bba0SGirish Moodalbail (void) fprintf(stderr, "%s: ", progname);
10596e91bba0SGirish Moodalbail
10606e91bba0SGirish Moodalbail va_start(alist, format);
10616e91bba0SGirish Moodalbail (void) vfprintf(stderr, format, alist);
10626e91bba0SGirish Moodalbail va_end(alist);
10636e91bba0SGirish Moodalbail
10646e91bba0SGirish Moodalbail (void) putchar('\n');
10656e91bba0SGirish Moodalbail
10666e91bba0SGirish Moodalbail ipadm_destroy_addrobj(ipaddr);
10676e91bba0SGirish Moodalbail ipadm_close(iph);
10686e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
10696e91bba0SGirish Moodalbail }
10706e91bba0SGirish Moodalbail
10716e91bba0SGirish Moodalbail static void
die_opterr(int opt,int opterr,const char * usage)10726e91bba0SGirish Moodalbail die_opterr(int opt, int opterr, const char *usage)
10736e91bba0SGirish Moodalbail {
10746e91bba0SGirish Moodalbail switch (opterr) {
10756e91bba0SGirish Moodalbail case ':':
10766e91bba0SGirish Moodalbail die("option '-%c' requires a value\nusage: %s", opt,
10776e91bba0SGirish Moodalbail gettext(usage));
10786e91bba0SGirish Moodalbail break;
10796e91bba0SGirish Moodalbail case '?':
10806e91bba0SGirish Moodalbail default:
10816e91bba0SGirish Moodalbail die("unrecognized option '-%c'\nusage: %s", opt,
10826e91bba0SGirish Moodalbail gettext(usage));
10836e91bba0SGirish Moodalbail break;
10846e91bba0SGirish Moodalbail }
10856e91bba0SGirish Moodalbail }
10866e91bba0SGirish Moodalbail
10876e91bba0SGirish Moodalbail /* PRINTFLIKE2 */
10886e91bba0SGirish Moodalbail static void
warn_ipadmerr(ipadm_status_t err,const char * format,...)10896e91bba0SGirish Moodalbail warn_ipadmerr(ipadm_status_t err, const char *format, ...)
10906e91bba0SGirish Moodalbail {
10916e91bba0SGirish Moodalbail va_list alist;
10926e91bba0SGirish Moodalbail
10936e91bba0SGirish Moodalbail format = gettext(format);
10946e91bba0SGirish Moodalbail (void) fprintf(stderr, gettext("%s: warning: "), progname);
10956e91bba0SGirish Moodalbail
10966e91bba0SGirish Moodalbail va_start(alist, format);
10976e91bba0SGirish Moodalbail (void) vfprintf(stderr, format, alist);
10986e91bba0SGirish Moodalbail va_end(alist);
10996e91bba0SGirish Moodalbail
11006e91bba0SGirish Moodalbail (void) fprintf(stderr, "%s\n", ipadm_status2str(err));
11016e91bba0SGirish Moodalbail }
11026e91bba0SGirish Moodalbail
11036e91bba0SGirish Moodalbail static void
process_static_addrargs(const char * use,char * addrarg,const char * aobjname)11046e91bba0SGirish Moodalbail process_static_addrargs(const char *use, char *addrarg, const char *aobjname)
11056e91bba0SGirish Moodalbail {
11066e91bba0SGirish Moodalbail int option;
11076e91bba0SGirish Moodalbail char *val;
11086e91bba0SGirish Moodalbail char *laddr = NULL;
11096e91bba0SGirish Moodalbail char *raddr = NULL;
11106e91bba0SGirish Moodalbail char *save_input_arg = addrarg;
11116e91bba0SGirish Moodalbail boolean_t found_mismatch = _B_FALSE;
11126e91bba0SGirish Moodalbail ipadm_status_t status;
11136e91bba0SGirish Moodalbail enum { A_LOCAL, A_REMOTE };
11146e91bba0SGirish Moodalbail static char *addr_optstr[] = {
11156e91bba0SGirish Moodalbail "local",
11166e91bba0SGirish Moodalbail "remote",
11176e91bba0SGirish Moodalbail NULL,
11186e91bba0SGirish Moodalbail };
11196e91bba0SGirish Moodalbail
11206e91bba0SGirish Moodalbail while (*addrarg != '\0') {
11216e91bba0SGirish Moodalbail option = getsubopt(&addrarg, addr_optstr, &val);
11226e91bba0SGirish Moodalbail switch (option) {
11236e91bba0SGirish Moodalbail case A_LOCAL:
11246e91bba0SGirish Moodalbail if (laddr != NULL)
11256e91bba0SGirish Moodalbail die("Multiple local addresses provided");
11266e91bba0SGirish Moodalbail laddr = val;
11276e91bba0SGirish Moodalbail break;
11286e91bba0SGirish Moodalbail case A_REMOTE:
11296e91bba0SGirish Moodalbail if (raddr != NULL)
11306e91bba0SGirish Moodalbail die("Multiple remote addresses provided");
11316e91bba0SGirish Moodalbail raddr = val;
11326e91bba0SGirish Moodalbail break;
11336e91bba0SGirish Moodalbail default:
11346e91bba0SGirish Moodalbail if (found_mismatch)
11356e91bba0SGirish Moodalbail die("Invalid address provided\nusage: %s", use);
11366e91bba0SGirish Moodalbail found_mismatch = _B_TRUE;
11376e91bba0SGirish Moodalbail break;
11386e91bba0SGirish Moodalbail }
11396e91bba0SGirish Moodalbail }
11406e91bba0SGirish Moodalbail if (raddr != NULL && laddr == NULL)
11416e91bba0SGirish Moodalbail die("Missing local address\nusage: %s", use);
11426e91bba0SGirish Moodalbail
11436e91bba0SGirish Moodalbail /* If only one address is provided, it is assumed a local address. */
11446e91bba0SGirish Moodalbail if (laddr == NULL) {
11456e91bba0SGirish Moodalbail if (found_mismatch)
11466e91bba0SGirish Moodalbail laddr = save_input_arg;
11476e91bba0SGirish Moodalbail else
11486e91bba0SGirish Moodalbail die("Missing local address\nusage: %s", use);
11496e91bba0SGirish Moodalbail }
11506e91bba0SGirish Moodalbail
11516e91bba0SGirish Moodalbail /* Initialize the addrobj for static addresses. */
11526e91bba0SGirish Moodalbail status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname, &ipaddr);
11536e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
11546e91bba0SGirish Moodalbail die("Error in creating address object: %s",
11556e91bba0SGirish Moodalbail ipadm_status2str(status));
11566e91bba0SGirish Moodalbail }
11576e91bba0SGirish Moodalbail
11586e91bba0SGirish Moodalbail /* Set the local and remote addresses */
11596e91bba0SGirish Moodalbail status = ipadm_set_addr(ipaddr, laddr, AF_UNSPEC);
11606e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
11616e91bba0SGirish Moodalbail die("Error in setting local address: %s",
11626e91bba0SGirish Moodalbail ipadm_status2str(status));
11636e91bba0SGirish Moodalbail }
11646e91bba0SGirish Moodalbail if (raddr != NULL) {
11656e91bba0SGirish Moodalbail status = ipadm_set_dst_addr(ipaddr, raddr, AF_UNSPEC);
11666e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
11676e91bba0SGirish Moodalbail die("Error in setting remote address: %s",
11686e91bba0SGirish Moodalbail ipadm_status2str(status));
11696e91bba0SGirish Moodalbail }
11706e91bba0SGirish Moodalbail }
11716e91bba0SGirish Moodalbail }
11726e91bba0SGirish Moodalbail
11736e91bba0SGirish Moodalbail static void
process_addrconf_addrargs(const char * use,char * addrarg)11746e91bba0SGirish Moodalbail process_addrconf_addrargs(const char *use, char *addrarg)
11756e91bba0SGirish Moodalbail {
11766e91bba0SGirish Moodalbail int option;
11776e91bba0SGirish Moodalbail char *val;
11786e91bba0SGirish Moodalbail enum { P_STATELESS, P_STATEFUL };
11796e91bba0SGirish Moodalbail static char *addr_optstr[] = {
11806e91bba0SGirish Moodalbail "stateless",
11816e91bba0SGirish Moodalbail "stateful",
11826e91bba0SGirish Moodalbail NULL,
11836e91bba0SGirish Moodalbail };
11846e91bba0SGirish Moodalbail boolean_t stateless;
11856e91bba0SGirish Moodalbail boolean_t stateless_arg = _B_FALSE;
11866e91bba0SGirish Moodalbail boolean_t stateful;
11876e91bba0SGirish Moodalbail boolean_t stateful_arg = _B_FALSE;
11886e91bba0SGirish Moodalbail ipadm_status_t status;
11896e91bba0SGirish Moodalbail
11906e91bba0SGirish Moodalbail while (*addrarg != '\0') {
11916e91bba0SGirish Moodalbail option = getsubopt(&addrarg, addr_optstr, &val);
11926e91bba0SGirish Moodalbail switch (option) {
11936e91bba0SGirish Moodalbail case P_STATELESS:
11946e91bba0SGirish Moodalbail if (stateless_arg)
11956e91bba0SGirish Moodalbail die("Duplicate option");
1196*7bc87895SYuri Pankov if (val == NULL)
1197*7bc87895SYuri Pankov die("Invalid argument");
11986e91bba0SGirish Moodalbail if (strcmp(val, "yes") == 0)
11996e91bba0SGirish Moodalbail stateless = _B_TRUE;
12006e91bba0SGirish Moodalbail else if (strcmp(val, "no") == 0)
12016e91bba0SGirish Moodalbail stateless = _B_FALSE;
12026e91bba0SGirish Moodalbail else
12036e91bba0SGirish Moodalbail die("Invalid argument");
12046e91bba0SGirish Moodalbail stateless_arg = _B_TRUE;
12056e91bba0SGirish Moodalbail break;
12066e91bba0SGirish Moodalbail case P_STATEFUL:
12076e91bba0SGirish Moodalbail if (stateful_arg)
12086e91bba0SGirish Moodalbail die("Duplicate option");
1209*7bc87895SYuri Pankov if (val == NULL)
1210*7bc87895SYuri Pankov die("Invalid argument");
12116e91bba0SGirish Moodalbail if (strcmp(val, "yes") == 0)
12126e91bba0SGirish Moodalbail stateful = _B_TRUE;
12136e91bba0SGirish Moodalbail else if (strcmp(val, "no") == 0)
12146e91bba0SGirish Moodalbail stateful = _B_FALSE;
12156e91bba0SGirish Moodalbail else
12166e91bba0SGirish Moodalbail die("Invalid argument");
12176e91bba0SGirish Moodalbail stateful_arg = _B_TRUE;
12186e91bba0SGirish Moodalbail break;
12196e91bba0SGirish Moodalbail default:
12206e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
12216e91bba0SGirish Moodalbail }
12226e91bba0SGirish Moodalbail }
12236e91bba0SGirish Moodalbail
12246e91bba0SGirish Moodalbail if (!stateless_arg && !stateful_arg)
12256e91bba0SGirish Moodalbail die("Invalid arguments for option -p");
12266e91bba0SGirish Moodalbail
12276e91bba0SGirish Moodalbail /* Set the addrobj fields for addrconf */
12286e91bba0SGirish Moodalbail if (stateless_arg) {
12296e91bba0SGirish Moodalbail status = ipadm_set_stateless(ipaddr, stateless);
12306e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
12316e91bba0SGirish Moodalbail die("Error in setting stateless option: %s",
12326e91bba0SGirish Moodalbail ipadm_status2str(status));
12336e91bba0SGirish Moodalbail }
12346e91bba0SGirish Moodalbail }
12356e91bba0SGirish Moodalbail if (stateful_arg) {
12366e91bba0SGirish Moodalbail status = ipadm_set_stateful(ipaddr, stateful);
12376e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
12386e91bba0SGirish Moodalbail die("Error in setting stateful option: %s",
12396e91bba0SGirish Moodalbail ipadm_status2str(status));
12406e91bba0SGirish Moodalbail }
12416e91bba0SGirish Moodalbail }
12426e91bba0SGirish Moodalbail }
12436e91bba0SGirish Moodalbail
12446e91bba0SGirish Moodalbail /*
12456e91bba0SGirish Moodalbail * Creates static, dhcp or addrconf addresses and associates the created
12466e91bba0SGirish Moodalbail * addresses with the specified address object name.
12476e91bba0SGirish Moodalbail */
12486e91bba0SGirish Moodalbail static void
do_create_addr(int argc,char * argv[],const char * use)12496e91bba0SGirish Moodalbail do_create_addr(int argc, char *argv[], const char *use)
12506e91bba0SGirish Moodalbail {
12516e91bba0SGirish Moodalbail ipadm_status_t status;
12526e91bba0SGirish Moodalbail int option;
12536e91bba0SGirish Moodalbail uint32_t flags =
1254f6da83d4SAnurag S. Maskey IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
12556e91bba0SGirish Moodalbail char *cp;
12566e91bba0SGirish Moodalbail char *atype = NULL;
12576e91bba0SGirish Moodalbail char *static_arg = NULL;
12586e91bba0SGirish Moodalbail char *addrconf_arg = NULL;
12596e91bba0SGirish Moodalbail char *interface_id = NULL;
12606e91bba0SGirish Moodalbail char *wait = NULL;
12616e91bba0SGirish Moodalbail boolean_t s_opt = _B_FALSE; /* static addr options */
12626e91bba0SGirish Moodalbail boolean_t auto_opt = _B_FALSE; /* Addrconf options */
12636e91bba0SGirish Moodalbail boolean_t dhcp_opt = _B_FALSE; /* dhcp options */
12646e91bba0SGirish Moodalbail
12656e91bba0SGirish Moodalbail opterr = 0;
12666e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":T:a:di:p:w:t",
12676e91bba0SGirish Moodalbail addr_longopts, NULL)) != -1) {
12686e91bba0SGirish Moodalbail switch (option) {
12696e91bba0SGirish Moodalbail case 'T':
12706e91bba0SGirish Moodalbail atype = optarg;
12716e91bba0SGirish Moodalbail break;
12726e91bba0SGirish Moodalbail case 'a':
12736e91bba0SGirish Moodalbail static_arg = optarg;
12746e91bba0SGirish Moodalbail s_opt = _B_TRUE;
12756e91bba0SGirish Moodalbail break;
12766e91bba0SGirish Moodalbail case 'd':
12776e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_UP;
12786e91bba0SGirish Moodalbail s_opt = _B_TRUE;
12796e91bba0SGirish Moodalbail break;
12806e91bba0SGirish Moodalbail case 'i':
12816e91bba0SGirish Moodalbail interface_id = optarg;
12826e91bba0SGirish Moodalbail auto_opt = _B_TRUE;
12836e91bba0SGirish Moodalbail break;
12846e91bba0SGirish Moodalbail case 'p':
12856e91bba0SGirish Moodalbail addrconf_arg = optarg;
12866e91bba0SGirish Moodalbail auto_opt = _B_TRUE;
12876e91bba0SGirish Moodalbail break;
12886e91bba0SGirish Moodalbail case 'w':
12896e91bba0SGirish Moodalbail wait = optarg;
12906e91bba0SGirish Moodalbail dhcp_opt = _B_TRUE;
12916e91bba0SGirish Moodalbail break;
12926e91bba0SGirish Moodalbail case 't':
12936e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
12946e91bba0SGirish Moodalbail break;
12956e91bba0SGirish Moodalbail default:
12966e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
12976e91bba0SGirish Moodalbail }
12986e91bba0SGirish Moodalbail }
12996e91bba0SGirish Moodalbail if (atype == NULL || optind != (argc - 1)) {
13006e91bba0SGirish Moodalbail die("Invalid arguments\nusage: %s", use);
13016e91bba0SGirish Moodalbail } else if ((cp = strchr(argv[optind], '/')) == NULL ||
13026e91bba0SGirish Moodalbail strlen(++cp) == 0) {
13036e91bba0SGirish Moodalbail die("invalid address object name: %s\nusage: %s",
13046e91bba0SGirish Moodalbail argv[optind], use);
13056e91bba0SGirish Moodalbail }
13066e91bba0SGirish Moodalbail
13076e91bba0SGirish Moodalbail /*
13086e91bba0SGirish Moodalbail * Allocate and initialize the addrobj based on the address type.
13096e91bba0SGirish Moodalbail */
13106e91bba0SGirish Moodalbail if (strcmp(atype, "static") == 0) {
13116e91bba0SGirish Moodalbail if (static_arg == NULL || auto_opt || dhcp_opt) {
13126e91bba0SGirish Moodalbail die("Invalid arguments for type %s\nusage: %s",
13136e91bba0SGirish Moodalbail atype, use);
13146e91bba0SGirish Moodalbail }
13156e91bba0SGirish Moodalbail process_static_addrargs(use, static_arg, argv[optind]);
13166e91bba0SGirish Moodalbail } else if (strcmp(atype, "dhcp") == 0) {
13176e91bba0SGirish Moodalbail if (auto_opt || s_opt) {
13186e91bba0SGirish Moodalbail die("Invalid arguments for type %s\nusage: %s",
13196e91bba0SGirish Moodalbail atype, use);
13206e91bba0SGirish Moodalbail }
13216e91bba0SGirish Moodalbail
13226e91bba0SGirish Moodalbail /* Initialize the addrobj for dhcp addresses. */
13236e91bba0SGirish Moodalbail status = ipadm_create_addrobj(IPADM_ADDR_DHCP, argv[optind],
13246e91bba0SGirish Moodalbail &ipaddr);
13256e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
13266e91bba0SGirish Moodalbail die("Error in creating address object: %s",
13276e91bba0SGirish Moodalbail ipadm_status2str(status));
13286e91bba0SGirish Moodalbail }
13296e91bba0SGirish Moodalbail if (wait != NULL) {
13306e91bba0SGirish Moodalbail int32_t ipadm_wait;
13316e91bba0SGirish Moodalbail
13326e91bba0SGirish Moodalbail if (strcmp(wait, "forever") == 0) {
13336e91bba0SGirish Moodalbail ipadm_wait = IPADM_DHCP_WAIT_FOREVER;
13346e91bba0SGirish Moodalbail } else {
13356e91bba0SGirish Moodalbail char *end;
13366e91bba0SGirish Moodalbail long timeout = strtol(wait, &end, 10);
13376e91bba0SGirish Moodalbail
13386e91bba0SGirish Moodalbail if (*end != '\0' || timeout < 0)
13396e91bba0SGirish Moodalbail die("Invalid argument");
13406e91bba0SGirish Moodalbail ipadm_wait = (int32_t)timeout;
13416e91bba0SGirish Moodalbail }
13426e91bba0SGirish Moodalbail status = ipadm_set_wait_time(ipaddr, ipadm_wait);
13436e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
13446e91bba0SGirish Moodalbail die("Error in setting wait time: %s",
13456e91bba0SGirish Moodalbail ipadm_status2str(status));
13466e91bba0SGirish Moodalbail }
13476e91bba0SGirish Moodalbail }
13486e91bba0SGirish Moodalbail } else if (strcmp(atype, "addrconf") == 0) {
13496e91bba0SGirish Moodalbail if (dhcp_opt || s_opt) {
13506e91bba0SGirish Moodalbail die("Invalid arguments for type %s\nusage: %s",
13516e91bba0SGirish Moodalbail atype, use);
13526e91bba0SGirish Moodalbail }
13536e91bba0SGirish Moodalbail
13546e91bba0SGirish Moodalbail /* Initialize the addrobj for dhcp addresses. */
13556e91bba0SGirish Moodalbail status = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
13566e91bba0SGirish Moodalbail argv[optind], &ipaddr);
13576e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
13586e91bba0SGirish Moodalbail die("Error in creating address object: %s",
13596e91bba0SGirish Moodalbail ipadm_status2str(status));
13606e91bba0SGirish Moodalbail }
13616e91bba0SGirish Moodalbail if (interface_id != NULL) {
13626e91bba0SGirish Moodalbail status = ipadm_set_interface_id(ipaddr, interface_id);
13636e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
13646e91bba0SGirish Moodalbail die("Error in setting interface ID: %s",
13656e91bba0SGirish Moodalbail ipadm_status2str(status));
13666e91bba0SGirish Moodalbail }
13676e91bba0SGirish Moodalbail }
13686e91bba0SGirish Moodalbail if (addrconf_arg)
13696e91bba0SGirish Moodalbail process_addrconf_addrargs(use, addrconf_arg);
13706e91bba0SGirish Moodalbail } else {
13716e91bba0SGirish Moodalbail die("Invalid address type %s", atype);
13726e91bba0SGirish Moodalbail }
13736e91bba0SGirish Moodalbail
13746e91bba0SGirish Moodalbail status = ipadm_create_addr(iph, ipaddr, flags);
13756e91bba0SGirish Moodalbail if (status == IPADM_DHCP_IPC_TIMEOUT)
13766e91bba0SGirish Moodalbail warn_ipadmerr(status, "");
13776e91bba0SGirish Moodalbail else if (status != IPADM_SUCCESS)
13786e91bba0SGirish Moodalbail die("Could not create address: %s", ipadm_status2str(status));
13796e91bba0SGirish Moodalbail }
13806e91bba0SGirish Moodalbail
13816e91bba0SGirish Moodalbail /*
13826e91bba0SGirish Moodalbail * Used by some address management functions to parse the command line
13836e91bba0SGirish Moodalbail * arguments and create `ipaddr' address object.
13846e91bba0SGirish Moodalbail */
13856e91bba0SGirish Moodalbail static void
process_misc_addrargs(int argc,char * argv[],const char * use,int * index,uint32_t * flags)13866e91bba0SGirish Moodalbail process_misc_addrargs(int argc, char *argv[], const char *use, int *index,
13876e91bba0SGirish Moodalbail uint32_t *flags)
13886e91bba0SGirish Moodalbail {
13896e91bba0SGirish Moodalbail int option;
13906e91bba0SGirish Moodalbail
13916e91bba0SGirish Moodalbail opterr = 0;
13926e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":t", addr_misc_longopts,
13936e91bba0SGirish Moodalbail NULL)) != -1) {
13946e91bba0SGirish Moodalbail switch (option) {
13956e91bba0SGirish Moodalbail case 't':
13966e91bba0SGirish Moodalbail *flags &= ~IPADM_OPT_PERSIST;
13976e91bba0SGirish Moodalbail break;
13986e91bba0SGirish Moodalbail default:
13996e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
14006e91bba0SGirish Moodalbail }
14016e91bba0SGirish Moodalbail }
14026e91bba0SGirish Moodalbail if (optind != (argc - 1))
14036e91bba0SGirish Moodalbail die("Usage: %s", use);
14046e91bba0SGirish Moodalbail
14056e91bba0SGirish Moodalbail *index = optind;
14066e91bba0SGirish Moodalbail }
14076e91bba0SGirish Moodalbail
14086e91bba0SGirish Moodalbail /*
14096e91bba0SGirish Moodalbail * Remove an addrobj from both active and persistent configuration.
14106e91bba0SGirish Moodalbail */
14116e91bba0SGirish Moodalbail static void
do_delete_addr(int argc,char * argv[],const char * use)14126e91bba0SGirish Moodalbail do_delete_addr(int argc, char *argv[], const char *use)
14136e91bba0SGirish Moodalbail {
14146e91bba0SGirish Moodalbail ipadm_status_t status;
14156e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14166e91bba0SGirish Moodalbail int option;
14176e91bba0SGirish Moodalbail
14186e91bba0SGirish Moodalbail opterr = 0;
14196e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":r", addr_misc_longopts,
14206e91bba0SGirish Moodalbail NULL)) != -1) {
14216e91bba0SGirish Moodalbail switch (option) {
14226e91bba0SGirish Moodalbail case 'r':
14236e91bba0SGirish Moodalbail flags |= IPADM_OPT_RELEASE;
14246e91bba0SGirish Moodalbail break;
14256e91bba0SGirish Moodalbail default:
14266e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
14276e91bba0SGirish Moodalbail }
14286e91bba0SGirish Moodalbail }
14296e91bba0SGirish Moodalbail if (optind != (argc - 1))
14306e91bba0SGirish Moodalbail die("Usage: %s", use);
14316e91bba0SGirish Moodalbail
14326e91bba0SGirish Moodalbail status = ipadm_delete_addr(iph, argv[optind], flags);
14336e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
14346e91bba0SGirish Moodalbail die("could not delete address: %s",
14356e91bba0SGirish Moodalbail ipadm_status2str(status));
14366e91bba0SGirish Moodalbail }
14376e91bba0SGirish Moodalbail }
14386e91bba0SGirish Moodalbail
14396e91bba0SGirish Moodalbail /*
14406e91bba0SGirish Moodalbail * Enable an IP address based on the persistent configuration for that
14416e91bba0SGirish Moodalbail * IP address
14426e91bba0SGirish Moodalbail */
14436e91bba0SGirish Moodalbail static void
do_enable_addr(int argc,char * argv[],const char * use)14446e91bba0SGirish Moodalbail do_enable_addr(int argc, char *argv[], const char *use)
14456e91bba0SGirish Moodalbail {
14466e91bba0SGirish Moodalbail ipadm_status_t status;
14476e91bba0SGirish Moodalbail int index;
14486e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14496e91bba0SGirish Moodalbail
14506e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
14516e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
14526e91bba0SGirish Moodalbail die("persistent operation not supported for enable-addr");
14536e91bba0SGirish Moodalbail
14546e91bba0SGirish Moodalbail status = ipadm_enable_addr(iph, argv[index], flags);
14556e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
14566e91bba0SGirish Moodalbail die("could not enable address: %s", ipadm_status2str(status));
14576e91bba0SGirish Moodalbail }
14586e91bba0SGirish Moodalbail
14596e91bba0SGirish Moodalbail /*
14606e91bba0SGirish Moodalbail * Mark the address identified by addrobj 'up'
14616e91bba0SGirish Moodalbail */
14626e91bba0SGirish Moodalbail static void
do_up_addr(int argc,char * argv[],const char * use)14636e91bba0SGirish Moodalbail do_up_addr(int argc, char *argv[], const char *use)
14646e91bba0SGirish Moodalbail {
14656e91bba0SGirish Moodalbail ipadm_status_t status;
14666e91bba0SGirish Moodalbail int index;
14676e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14686e91bba0SGirish Moodalbail
14696e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
14706e91bba0SGirish Moodalbail status = ipadm_up_addr(iph, argv[index], flags);
14716e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
14726e91bba0SGirish Moodalbail die("Could not mark the address up: %s",
14736e91bba0SGirish Moodalbail ipadm_status2str(status));
14746e91bba0SGirish Moodalbail }
14756e91bba0SGirish Moodalbail }
14766e91bba0SGirish Moodalbail
14776e91bba0SGirish Moodalbail /*
14786e91bba0SGirish Moodalbail * Disable the specified addrobj by removing it from active cofiguration
14796e91bba0SGirish Moodalbail */
14806e91bba0SGirish Moodalbail static void
do_disable_addr(int argc,char * argv[],const char * use)14816e91bba0SGirish Moodalbail do_disable_addr(int argc, char *argv[], const char *use)
14826e91bba0SGirish Moodalbail {
14836e91bba0SGirish Moodalbail ipadm_status_t status;
14846e91bba0SGirish Moodalbail int index;
14856e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14866e91bba0SGirish Moodalbail
14876e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
14886e91bba0SGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
14896e91bba0SGirish Moodalbail die("persistent operation not supported for disable-addr");
14906e91bba0SGirish Moodalbail
14916e91bba0SGirish Moodalbail status = ipadm_disable_addr(iph, argv[index], flags);
14926e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
14936e91bba0SGirish Moodalbail die("could not disable address: %s",
14946e91bba0SGirish Moodalbail ipadm_status2str(status));
14956e91bba0SGirish Moodalbail }
14966e91bba0SGirish Moodalbail }
14976e91bba0SGirish Moodalbail
14986e91bba0SGirish Moodalbail /*
14996e91bba0SGirish Moodalbail * Mark the address identified by addrobj 'down'
15006e91bba0SGirish Moodalbail */
15016e91bba0SGirish Moodalbail static void
do_down_addr(int argc,char * argv[],const char * use)15026e91bba0SGirish Moodalbail do_down_addr(int argc, char *argv[], const char *use)
15036e91bba0SGirish Moodalbail {
15046e91bba0SGirish Moodalbail ipadm_status_t status;
15056e91bba0SGirish Moodalbail int index;
15066e91bba0SGirish Moodalbail uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
15076e91bba0SGirish Moodalbail
15086e91bba0SGirish Moodalbail process_misc_addrargs(argc, argv, use, &index, &flags);
15096e91bba0SGirish Moodalbail status = ipadm_down_addr(iph, argv[index], flags);
15106e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
15116e91bba0SGirish Moodalbail die("Could not mark the address down: %s",
15126e91bba0SGirish Moodalbail ipadm_status2str(status));
15136e91bba0SGirish Moodalbail }
15146e91bba0SGirish Moodalbail
15156e91bba0SGirish Moodalbail /*
15166e91bba0SGirish Moodalbail * Restart DAD for static address. Extend lease duration for DHCP addresses
15176e91bba0SGirish Moodalbail */
15186e91bba0SGirish Moodalbail static void
do_refresh_addr(int argc,char * argv[],const char * use)15196e91bba0SGirish Moodalbail do_refresh_addr(int argc, char *argv[], const char *use)
15206e91bba0SGirish Moodalbail {
15216e91bba0SGirish Moodalbail ipadm_status_t status;
15226e91bba0SGirish Moodalbail int option;
15236e91bba0SGirish Moodalbail uint32_t flags = 0;
15246e91bba0SGirish Moodalbail
15256e91bba0SGirish Moodalbail opterr = 0;
15266e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":i", addr_misc_longopts,
15276e91bba0SGirish Moodalbail NULL)) != -1) {
15286e91bba0SGirish Moodalbail switch (option) {
15296e91bba0SGirish Moodalbail case 'i':
15306e91bba0SGirish Moodalbail flags |= IPADM_OPT_INFORM;
15316e91bba0SGirish Moodalbail break;
15326e91bba0SGirish Moodalbail default:
15336e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
15346e91bba0SGirish Moodalbail }
15356e91bba0SGirish Moodalbail }
15366e91bba0SGirish Moodalbail if (optind != (argc - 1))
15376e91bba0SGirish Moodalbail die("Usage: %s", use);
15386e91bba0SGirish Moodalbail
15396e91bba0SGirish Moodalbail status = ipadm_refresh_addr(iph, argv[optind], flags);
15406e91bba0SGirish Moodalbail if (status == IPADM_DHCP_IPC_TIMEOUT)
15416e91bba0SGirish Moodalbail warn_ipadmerr(status, "");
15426e91bba0SGirish Moodalbail else if (status != IPADM_SUCCESS)
15436e91bba0SGirish Moodalbail die("could not refresh address %s", ipadm_status2str(status));
15446e91bba0SGirish Moodalbail }
15456e91bba0SGirish Moodalbail
15466e91bba0SGirish Moodalbail static void
sockaddr2str(const struct sockaddr_storage * ssp,char * buf,uint_t bufsize)15476e91bba0SGirish Moodalbail sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
15486e91bba0SGirish Moodalbail {
15496e91bba0SGirish Moodalbail socklen_t socklen;
15506e91bba0SGirish Moodalbail struct sockaddr *sp = (struct sockaddr *)ssp;
15516e91bba0SGirish Moodalbail
15526e91bba0SGirish Moodalbail switch (ssp->ss_family) {
15536e91bba0SGirish Moodalbail case AF_INET:
15546e91bba0SGirish Moodalbail socklen = sizeof (struct sockaddr_in);
15556e91bba0SGirish Moodalbail break;
15566e91bba0SGirish Moodalbail case AF_INET6:
15576e91bba0SGirish Moodalbail socklen = sizeof (struct sockaddr_in6);
15586e91bba0SGirish Moodalbail break;
15596e91bba0SGirish Moodalbail default:
15606e91bba0SGirish Moodalbail (void) strlcpy(buf, STR_UNKNOWN_VAL, bufsize);
15616e91bba0SGirish Moodalbail return;
15626e91bba0SGirish Moodalbail }
15636e91bba0SGirish Moodalbail
15646e91bba0SGirish Moodalbail (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0,
15656e91bba0SGirish Moodalbail (NI_NOFQDN | NI_NUMERICHOST));
15666e91bba0SGirish Moodalbail }
15676e91bba0SGirish Moodalbail
15686e91bba0SGirish Moodalbail static void
flags2str(uint64_t flags,fmask_t * tbl,boolean_t is_bits,char * buf,uint_t bufsize)15696e91bba0SGirish Moodalbail flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
15706e91bba0SGirish Moodalbail char *buf, uint_t bufsize)
15716e91bba0SGirish Moodalbail {
15726e91bba0SGirish Moodalbail int i;
15736e91bba0SGirish Moodalbail boolean_t first = _B_TRUE;
15746e91bba0SGirish Moodalbail
15756e91bba0SGirish Moodalbail if (is_bits) {
15766e91bba0SGirish Moodalbail for (i = 0; tbl[i].name; i++) {
15776e91bba0SGirish Moodalbail if ((flags & tbl[i].mask) == tbl[i].bits)
15786e91bba0SGirish Moodalbail (void) strlcat(buf, tbl[i].name, bufsize);
15796e91bba0SGirish Moodalbail else
15806e91bba0SGirish Moodalbail (void) strlcat(buf, "-", bufsize);
15816e91bba0SGirish Moodalbail }
15826e91bba0SGirish Moodalbail } else {
15836e91bba0SGirish Moodalbail for (i = 0; tbl[i].name; i++) {
15846e91bba0SGirish Moodalbail if ((flags & tbl[i].mask) == tbl[i].bits) {
15856e91bba0SGirish Moodalbail if (!first)
15866e91bba0SGirish Moodalbail (void) strlcat(buf, ",", bufsize);
15876e91bba0SGirish Moodalbail (void) strlcat(buf, tbl[i].name, bufsize);
15886e91bba0SGirish Moodalbail first = _B_FALSE;
15896e91bba0SGirish Moodalbail }
15906e91bba0SGirish Moodalbail }
15916e91bba0SGirish Moodalbail }
15926e91bba0SGirish Moodalbail }
15936e91bba0SGirish Moodalbail
1594550b6e40SSowmini Varadhan /*
1595550b6e40SSowmini Varadhan * return true if the address for lifname comes to us from the global zone
1596550b6e40SSowmini Varadhan * with 'allowed-ips' constraints.
1597550b6e40SSowmini Varadhan */
1598550b6e40SSowmini Varadhan static boolean_t
is_from_gz(const char * lifname)1599550b6e40SSowmini Varadhan is_from_gz(const char *lifname)
1600550b6e40SSowmini Varadhan {
1601550b6e40SSowmini Varadhan ipadm_if_info_t *if_info;
1602550b6e40SSowmini Varadhan char phyname[LIFNAMSIZ], *cp;
1603550b6e40SSowmini Varadhan boolean_t ret = _B_FALSE;
1604550b6e40SSowmini Varadhan ipadm_status_t status;
1605550b6e40SSowmini Varadhan zoneid_t zoneid;
1606550b6e40SSowmini Varadhan ushort_t zflags;
1607550b6e40SSowmini Varadhan
1608550b6e40SSowmini Varadhan if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
1609550b6e40SSowmini Varadhan return (_B_FALSE); /* from-gz only makes sense in a NGZ */
1610550b6e40SSowmini Varadhan
1611550b6e40SSowmini Varadhan if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
1612550b6e40SSowmini Varadhan return (_B_FALSE);
1613550b6e40SSowmini Varadhan
1614550b6e40SSowmini Varadhan if (!(zflags & ZF_NET_EXCL))
1615550b6e40SSowmini Varadhan return (_B_TRUE); /* everything is from the GZ for shared-ip */
1616550b6e40SSowmini Varadhan
1617550b6e40SSowmini Varadhan (void) strncpy(phyname, lifname, sizeof (phyname));
1618550b6e40SSowmini Varadhan if ((cp = strchr(phyname, ':')) != NULL)
1619550b6e40SSowmini Varadhan *cp = '\0';
1620550b6e40SSowmini Varadhan status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
1621550b6e40SSowmini Varadhan if (status != IPADM_SUCCESS)
1622550b6e40SSowmini Varadhan return (ret);
1623550b6e40SSowmini Varadhan
1624550b6e40SSowmini Varadhan if (if_info->ifi_cflags & IFIF_L3PROTECT)
1625550b6e40SSowmini Varadhan ret = _B_TRUE;
1626550b6e40SSowmini Varadhan if (if_info)
1627550b6e40SSowmini Varadhan ipadm_free_if_info(if_info);
1628550b6e40SSowmini Varadhan return (ret);
1629550b6e40SSowmini Varadhan }
1630550b6e40SSowmini Varadhan
16316e91bba0SGirish Moodalbail static boolean_t
print_sa_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)16326e91bba0SGirish Moodalbail print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
16336e91bba0SGirish Moodalbail {
16346e91bba0SGirish Moodalbail show_addr_args_t *arg = ofarg->ofmt_cbarg;
16356e91bba0SGirish Moodalbail ipadm_addr_info_t *ainfo = arg->sa_info;
16366e91bba0SGirish Moodalbail char interface[LIFNAMSIZ];
16376e91bba0SGirish Moodalbail char addrbuf[MAXPROPVALLEN];
16386e91bba0SGirish Moodalbail char dstbuf[MAXPROPVALLEN];
16396e91bba0SGirish Moodalbail char prefixlenstr[MAXPROPVALLEN];
16406e91bba0SGirish Moodalbail int prefixlen;
16416e91bba0SGirish Moodalbail struct sockaddr_in *sin;
16426e91bba0SGirish Moodalbail struct sockaddr_in6 *sin6;
16436e91bba0SGirish Moodalbail sa_family_t af;
16446e91bba0SGirish Moodalbail char *phyname = NULL;
16456e91bba0SGirish Moodalbail struct ifaddrs *ifa = &ainfo->ia_ifa;
16466e91bba0SGirish Moodalbail fmask_t cflags_mask[] = {
16476e91bba0SGirish Moodalbail { "U", IA_UP, IA_UP },
16486e91bba0SGirish Moodalbail { "u", IA_UNNUMBERED, IA_UNNUMBERED },
16496e91bba0SGirish Moodalbail { "p", IA_PRIVATE, IA_PRIVATE },
16506e91bba0SGirish Moodalbail { "t", IA_TEMPORARY, IA_TEMPORARY },
16516e91bba0SGirish Moodalbail { "d", IA_DEPRECATED, IA_DEPRECATED },
16526e91bba0SGirish Moodalbail { NULL, 0, 0 }
16536e91bba0SGirish Moodalbail };
16546e91bba0SGirish Moodalbail fmask_t pflags_mask[] = {
16556e91bba0SGirish Moodalbail { "U", IA_UP, IA_UP },
16566e91bba0SGirish Moodalbail { "p", IA_PRIVATE, IA_PRIVATE },
16576e91bba0SGirish Moodalbail { "d", IA_DEPRECATED, IA_DEPRECATED },
16586e91bba0SGirish Moodalbail { NULL, 0, 0 }
16596e91bba0SGirish Moodalbail };
16606e91bba0SGirish Moodalbail fmask_t type[] = {
16616e91bba0SGirish Moodalbail { "static", IPADM_ADDR_STATIC, IPADM_ALL_BITS},
16626e91bba0SGirish Moodalbail { "addrconf", IPADM_ADDR_IPV6_ADDRCONF, IPADM_ALL_BITS},
16636e91bba0SGirish Moodalbail { "dhcp", IPADM_ADDR_DHCP, IPADM_ALL_BITS},
16646e91bba0SGirish Moodalbail { NULL, 0, 0 }
16656e91bba0SGirish Moodalbail };
16666e91bba0SGirish Moodalbail fmask_t addr_state[] = {
16676e91bba0SGirish Moodalbail { "disabled", IFA_DISABLED, IPADM_ALL_BITS},
16686e91bba0SGirish Moodalbail { "duplicate", IFA_DUPLICATE, IPADM_ALL_BITS},
16696e91bba0SGirish Moodalbail { "down", IFA_DOWN, IPADM_ALL_BITS},
16706e91bba0SGirish Moodalbail { "tentative", IFA_TENTATIVE, IPADM_ALL_BITS},
16716e91bba0SGirish Moodalbail { "ok", IFA_OK, IPADM_ALL_BITS},
16726e91bba0SGirish Moodalbail { "inaccessible", IFA_INACCESSIBLE, IPADM_ALL_BITS},
16736e91bba0SGirish Moodalbail { NULL, 0, 0 }
16746e91bba0SGirish Moodalbail };
16756e91bba0SGirish Moodalbail
16766e91bba0SGirish Moodalbail buf[0] = '\0';
16776e91bba0SGirish Moodalbail switch (ofarg->ofmt_id) {
16786e91bba0SGirish Moodalbail case SA_ADDROBJ:
16796e91bba0SGirish Moodalbail if (ainfo->ia_aobjname[0] == '\0') {
16806e91bba0SGirish Moodalbail (void) strncpy(interface, ifa->ifa_name, LIFNAMSIZ);
16816e91bba0SGirish Moodalbail phyname = strrchr(interface, ':');
16826e91bba0SGirish Moodalbail if (phyname)
16836e91bba0SGirish Moodalbail *phyname = '\0';
16846e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s/%s", interface,
16856e91bba0SGirish Moodalbail STR_UNKNOWN_VAL);
16866e91bba0SGirish Moodalbail } else {
16876e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", ainfo->ia_aobjname);
16886e91bba0SGirish Moodalbail }
16896e91bba0SGirish Moodalbail break;
16906e91bba0SGirish Moodalbail case SA_STATE:
16916e91bba0SGirish Moodalbail flags2str(ainfo->ia_state, addr_state, _B_FALSE,
16926e91bba0SGirish Moodalbail buf, bufsize);
16936e91bba0SGirish Moodalbail break;
16946e91bba0SGirish Moodalbail case SA_TYPE:
1695550b6e40SSowmini Varadhan if (is_from_gz(ifa->ifa_name))
1696550b6e40SSowmini Varadhan (void) snprintf(buf, bufsize, "from-gz");
1697550b6e40SSowmini Varadhan else
1698550b6e40SSowmini Varadhan flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
1699550b6e40SSowmini Varadhan bufsize);
17006e91bba0SGirish Moodalbail break;
17016e91bba0SGirish Moodalbail case SA_CURRENT:
17026e91bba0SGirish Moodalbail flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
17036e91bba0SGirish Moodalbail break;
17046e91bba0SGirish Moodalbail case SA_PERSISTENT:
17056e91bba0SGirish Moodalbail flags2str(ainfo->ia_pflags, pflags_mask, _B_TRUE, buf, bufsize);
17066e91bba0SGirish Moodalbail break;
17076e91bba0SGirish Moodalbail case SA_ADDR:
170864639aafSDarren Reed af = ifa->ifa_addr->sa_family;
17096e91bba0SGirish Moodalbail /*
17106e91bba0SGirish Moodalbail * If the address is 0.0.0.0 or :: and the origin is DHCP,
17116e91bba0SGirish Moodalbail * print STR_UNKNOWN_VAL.
17126e91bba0SGirish Moodalbail */
17136e91bba0SGirish Moodalbail if (ainfo->ia_atype == IPADM_ADDR_DHCP) {
17146e91bba0SGirish Moodalbail sin = (struct sockaddr_in *)ifa->ifa_addr;
17156e91bba0SGirish Moodalbail sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
17166e91bba0SGirish Moodalbail if ((af == AF_INET &&
17176e91bba0SGirish Moodalbail sin->sin_addr.s_addr == INADDR_ANY) ||
17186e91bba0SGirish Moodalbail (af == AF_INET6 &&
17196e91bba0SGirish Moodalbail IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
17206e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, STR_UNKNOWN_VAL);
17216e91bba0SGirish Moodalbail break;
17226e91bba0SGirish Moodalbail }
17236e91bba0SGirish Moodalbail }
17246e91bba0SGirish Moodalbail if (ifa->ifa_netmask == NULL)
17256e91bba0SGirish Moodalbail prefixlen = 0;
17266e91bba0SGirish Moodalbail else
17276e91bba0SGirish Moodalbail prefixlen = mask2plen(ifa->ifa_netmask);
17286e91bba0SGirish Moodalbail bzero(prefixlenstr, sizeof (prefixlenstr));
17296e91bba0SGirish Moodalbail if (prefixlen > 0) {
17306e91bba0SGirish Moodalbail (void) snprintf(prefixlenstr, sizeof (prefixlenstr),
17316e91bba0SGirish Moodalbail "/%d", prefixlen);
17326e91bba0SGirish Moodalbail }
17336e91bba0SGirish Moodalbail bzero(addrbuf, sizeof (addrbuf));
17346e91bba0SGirish Moodalbail bzero(dstbuf, sizeof (dstbuf));
17356e91bba0SGirish Moodalbail if (ainfo->ia_atype == IPADM_ADDR_STATIC) {
17366e91bba0SGirish Moodalbail /*
17376e91bba0SGirish Moodalbail * Print the hostname fields if the address is not
17386e91bba0SGirish Moodalbail * in active configuration.
17396e91bba0SGirish Moodalbail */
17406e91bba0SGirish Moodalbail if (ainfo->ia_state == IFA_DISABLED) {
17416e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s",
17426e91bba0SGirish Moodalbail ainfo->ia_sname);
17436e91bba0SGirish Moodalbail if (ainfo->ia_dname[0] != '\0') {
17446e91bba0SGirish Moodalbail (void) snprintf(dstbuf, sizeof (dstbuf),
17456e91bba0SGirish Moodalbail "->%s", ainfo->ia_dname);
17466e91bba0SGirish Moodalbail (void) strlcat(buf, dstbuf, bufsize);
17476e91bba0SGirish Moodalbail } else {
17486e91bba0SGirish Moodalbail (void) strlcat(buf, prefixlenstr,
17496e91bba0SGirish Moodalbail bufsize);
17506e91bba0SGirish Moodalbail }
17516e91bba0SGirish Moodalbail break;
17526e91bba0SGirish Moodalbail }
175308ed54f3SVasumathi Sundaram }
17546e91bba0SGirish Moodalbail /*
17556e91bba0SGirish Moodalbail * For the non-persistent case, we need to show the
17566e91bba0SGirish Moodalbail * currently configured addresses for source and
17576e91bba0SGirish Moodalbail * destination.
17586e91bba0SGirish Moodalbail */
175908ed54f3SVasumathi Sundaram sockaddr2str((struct sockaddr_storage *)ifa->ifa_addr,
176008ed54f3SVasumathi Sundaram addrbuf, sizeof (addrbuf));
17616e91bba0SGirish Moodalbail if (ifa->ifa_flags & IFF_POINTOPOINT) {
17626e91bba0SGirish Moodalbail sockaddr2str(
17636e91bba0SGirish Moodalbail (struct sockaddr_storage *)ifa->ifa_dstaddr,
17646e91bba0SGirish Moodalbail dstbuf, sizeof (dstbuf));
17656e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s->%s", addrbuf,
17666e91bba0SGirish Moodalbail dstbuf);
17676e91bba0SGirish Moodalbail } else {
17686e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s%s", addrbuf,
17696e91bba0SGirish Moodalbail prefixlenstr);
17706e91bba0SGirish Moodalbail }
17716e91bba0SGirish Moodalbail break;
17726e91bba0SGirish Moodalbail default:
17736e91bba0SGirish Moodalbail die("invalid input");
17746e91bba0SGirish Moodalbail break;
17756e91bba0SGirish Moodalbail }
17766e91bba0SGirish Moodalbail
17776e91bba0SGirish Moodalbail return (_B_TRUE);
17786e91bba0SGirish Moodalbail }
17796e91bba0SGirish Moodalbail
17806e91bba0SGirish Moodalbail /*
17816e91bba0SGirish Moodalbail * Display address information, either for the given address or
17826e91bba0SGirish Moodalbail * for all the addresses managed by ipadm.
17836e91bba0SGirish Moodalbail */
17846e91bba0SGirish Moodalbail static void
do_show_addr(int argc,char * argv[],const char * use)17856e91bba0SGirish Moodalbail do_show_addr(int argc, char *argv[], const char *use)
17866e91bba0SGirish Moodalbail {
17876e91bba0SGirish Moodalbail ipadm_status_t status;
17886e91bba0SGirish Moodalbail show_addr_state_t state;
17896e91bba0SGirish Moodalbail char *def_fields_str = "addrobj,type,state,addr";
17906e91bba0SGirish Moodalbail char *fields_str = NULL;
17916e91bba0SGirish Moodalbail ipadm_addr_info_t *ainfo;
17926e91bba0SGirish Moodalbail ipadm_addr_info_t *ptr;
17936e91bba0SGirish Moodalbail show_addr_args_t sargs;
17946e91bba0SGirish Moodalbail int option;
17956e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
17966e91bba0SGirish Moodalbail ofmt_status_t oferr;
17976e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
17986e91bba0SGirish Moodalbail char *aname;
17996e91bba0SGirish Moodalbail char *ifname = NULL;
18006e91bba0SGirish Moodalbail char *cp;
18016e91bba0SGirish Moodalbail boolean_t found = _B_FALSE;
18026e91bba0SGirish Moodalbail
18036e91bba0SGirish Moodalbail opterr = 0;
18046e91bba0SGirish Moodalbail state.sa_parsable = _B_FALSE;
18056e91bba0SGirish Moodalbail state.sa_persist = _B_FALSE;
18066e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, "po:", show_addr_longopts,
18076e91bba0SGirish Moodalbail NULL)) != -1) {
18086e91bba0SGirish Moodalbail switch (option) {
18096e91bba0SGirish Moodalbail case 'p':
18106e91bba0SGirish Moodalbail state.sa_parsable = _B_TRUE;
18116e91bba0SGirish Moodalbail break;
18126e91bba0SGirish Moodalbail case 'o':
18136e91bba0SGirish Moodalbail fields_str = optarg;
18146e91bba0SGirish Moodalbail break;
18156e91bba0SGirish Moodalbail default:
18166e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
18176e91bba0SGirish Moodalbail break;
18186e91bba0SGirish Moodalbail }
18196e91bba0SGirish Moodalbail }
18206e91bba0SGirish Moodalbail if (state.sa_parsable && fields_str == NULL)
18216e91bba0SGirish Moodalbail die("-p requires -o");
18226e91bba0SGirish Moodalbail
18236e91bba0SGirish Moodalbail if (optind == argc - 1) {
18246e91bba0SGirish Moodalbail aname = argv[optind];
18256e91bba0SGirish Moodalbail if ((cp = strchr(aname, '/')) == NULL)
18266e91bba0SGirish Moodalbail die("Invalid address object name provided");
18276e91bba0SGirish Moodalbail if (*(cp + 1) == '\0') {
18286e91bba0SGirish Moodalbail ifname = aname;
18296e91bba0SGirish Moodalbail *cp = '\0';
18306e91bba0SGirish Moodalbail aname = NULL;
18316e91bba0SGirish Moodalbail }
18326e91bba0SGirish Moodalbail } else if (optind == argc) {
18336e91bba0SGirish Moodalbail aname = NULL;
18346e91bba0SGirish Moodalbail } else {
18356e91bba0SGirish Moodalbail die("Usage: %s", use);
18366e91bba0SGirish Moodalbail }
18376e91bba0SGirish Moodalbail
18386e91bba0SGirish Moodalbail if (state.sa_parsable)
18396e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
18406e91bba0SGirish Moodalbail if (fields_str == NULL)
18416e91bba0SGirish Moodalbail fields_str = def_fields_str;
18426e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
18436e91bba0SGirish Moodalbail
18446e91bba0SGirish Moodalbail ipadm_ofmt_check(oferr, state.sa_parsable, ofmt);
18456e91bba0SGirish Moodalbail state.sa_ofmt = ofmt;
18466e91bba0SGirish Moodalbail
18476e91bba0SGirish Moodalbail status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
18486e91bba0SGirish Moodalbail /*
18496e91bba0SGirish Moodalbail * Return without printing any error, if no addresses were found,
18506e91bba0SGirish Moodalbail * for the case where all addresses are requested.
18516e91bba0SGirish Moodalbail */
18526e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
18536e91bba0SGirish Moodalbail die("Could not get address: %s", ipadm_status2str(status));
18546e91bba0SGirish Moodalbail if (ainfo == NULL) {
18556e91bba0SGirish Moodalbail ofmt_close(ofmt);
18566e91bba0SGirish Moodalbail return;
18576e91bba0SGirish Moodalbail }
18586e91bba0SGirish Moodalbail
18596e91bba0SGirish Moodalbail bzero(&sargs, sizeof (sargs));
18606e91bba0SGirish Moodalbail sargs.sa_state = &state;
18616e91bba0SGirish Moodalbail for (ptr = ainfo; ptr != NULL; ptr = IA_NEXT(ptr)) {
18626e91bba0SGirish Moodalbail sargs.sa_info = ptr;
18636e91bba0SGirish Moodalbail if (aname != NULL) {
18646e91bba0SGirish Moodalbail if (strcmp(sargs.sa_info->ia_aobjname, aname) != 0)
18656e91bba0SGirish Moodalbail continue;
18666e91bba0SGirish Moodalbail found = _B_TRUE;
18676e91bba0SGirish Moodalbail }
18686e91bba0SGirish Moodalbail ofmt_print(state.sa_ofmt, &sargs);
18696e91bba0SGirish Moodalbail }
18706e91bba0SGirish Moodalbail if (ainfo)
18716e91bba0SGirish Moodalbail ipadm_free_addr_info(ainfo);
18726e91bba0SGirish Moodalbail if (aname != NULL && !found)
18736e91bba0SGirish Moodalbail die("Address object not found");
18746e91bba0SGirish Moodalbail }
18756e91bba0SGirish Moodalbail
18766e91bba0SGirish Moodalbail static boolean_t
print_si_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)18776e91bba0SGirish Moodalbail print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
18786e91bba0SGirish Moodalbail {
18796e91bba0SGirish Moodalbail show_if_args_t *arg = ofarg->ofmt_cbarg;
18806e91bba0SGirish Moodalbail ipadm_if_info_t *ifinfo = arg->si_info;
18816e91bba0SGirish Moodalbail char *ifname = ifinfo->ifi_name;
18826e91bba0SGirish Moodalbail fmask_t intf_state[] = {
18836e91bba0SGirish Moodalbail { "ok", IFIS_OK, IPADM_ALL_BITS},
18846e91bba0SGirish Moodalbail { "down", IFIS_DOWN, IPADM_ALL_BITS},
18856e91bba0SGirish Moodalbail { "disabled", IFIS_DISABLED, IPADM_ALL_BITS},
18866e91bba0SGirish Moodalbail { "failed", IFIS_FAILED, IPADM_ALL_BITS},
18876e91bba0SGirish Moodalbail { "offline", IFIS_OFFLINE, IPADM_ALL_BITS},
18886e91bba0SGirish Moodalbail { NULL, 0, 0 }
18896e91bba0SGirish Moodalbail };
18906e91bba0SGirish Moodalbail fmask_t intf_pflags[] = {
18916e91bba0SGirish Moodalbail { "s", IFIF_STANDBY, IFIF_STANDBY },
18926e91bba0SGirish Moodalbail { "4", IFIF_IPV4, IFIF_IPV4 },
18936e91bba0SGirish Moodalbail { "6", IFIF_IPV6, IFIF_IPV6 },
18946e91bba0SGirish Moodalbail { NULL, 0, 0 }
18956e91bba0SGirish Moodalbail };
18966e91bba0SGirish Moodalbail fmask_t intf_cflags[] = {
18976e91bba0SGirish Moodalbail { "b", IFIF_BROADCAST, IFIF_BROADCAST },
18986e91bba0SGirish Moodalbail { "m", IFIF_MULTICAST, IFIF_MULTICAST },
18996e91bba0SGirish Moodalbail { "p", IFIF_POINTOPOINT, IFIF_POINTOPOINT},
19006e91bba0SGirish Moodalbail { "v", IFIF_VIRTUAL, IFIF_VIRTUAL },
19016e91bba0SGirish Moodalbail { "I", IFIF_IPMP, IFIF_IPMP },
19026e91bba0SGirish Moodalbail { "s", IFIF_STANDBY, IFIF_STANDBY },
19036e91bba0SGirish Moodalbail { "i", IFIF_INACTIVE, IFIF_INACTIVE },
19046e91bba0SGirish Moodalbail { "V", IFIF_VRRP, IFIF_VRRP },
19056e91bba0SGirish Moodalbail { "a", IFIF_NOACCEPT, IFIF_NOACCEPT },
1906550b6e40SSowmini Varadhan { "Z", IFIF_L3PROTECT, IFIF_L3PROTECT },
19076e91bba0SGirish Moodalbail { "4", IFIF_IPV4, IFIF_IPV4 },
19086e91bba0SGirish Moodalbail { "6", IFIF_IPV6, IFIF_IPV6 },
19096e91bba0SGirish Moodalbail { NULL, 0, 0 }
19106e91bba0SGirish Moodalbail };
19116e91bba0SGirish Moodalbail
19126e91bba0SGirish Moodalbail buf[0] = '\0';
19136e91bba0SGirish Moodalbail switch (ofarg->ofmt_id) {
19146e91bba0SGirish Moodalbail case SI_IFNAME:
19156e91bba0SGirish Moodalbail (void) snprintf(buf, bufsize, "%s", ifname);
19166e91bba0SGirish Moodalbail break;
19176e91bba0SGirish Moodalbail case SI_STATE:
19186e91bba0SGirish Moodalbail flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
19196e91bba0SGirish Moodalbail buf, bufsize);
19206e91bba0SGirish Moodalbail break;
19216e91bba0SGirish Moodalbail case SI_CURRENT:
19226e91bba0SGirish Moodalbail flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
19236e91bba0SGirish Moodalbail buf, bufsize);
19246e91bba0SGirish Moodalbail break;
19256e91bba0SGirish Moodalbail case SI_PERSISTENT:
19266e91bba0SGirish Moodalbail flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
19276e91bba0SGirish Moodalbail buf, bufsize);
19286e91bba0SGirish Moodalbail break;
19296e91bba0SGirish Moodalbail default:
19306e91bba0SGirish Moodalbail die("invalid input");
19316e91bba0SGirish Moodalbail break;
19326e91bba0SGirish Moodalbail }
19336e91bba0SGirish Moodalbail
19346e91bba0SGirish Moodalbail return (_B_TRUE);
19356e91bba0SGirish Moodalbail }
19366e91bba0SGirish Moodalbail
19376e91bba0SGirish Moodalbail /*
19386e91bba0SGirish Moodalbail * Display interface information, either for the given interface or
19396e91bba0SGirish Moodalbail * for all the interfaces in the system.
19406e91bba0SGirish Moodalbail */
19416e91bba0SGirish Moodalbail static void
do_show_if(int argc,char * argv[],const char * use)19426e91bba0SGirish Moodalbail do_show_if(int argc, char *argv[], const char *use)
19436e91bba0SGirish Moodalbail {
19446e91bba0SGirish Moodalbail ipadm_status_t status;
19456e91bba0SGirish Moodalbail show_if_state_t state;
19466e91bba0SGirish Moodalbail char *fields_str = NULL;
19476e91bba0SGirish Moodalbail ipadm_if_info_t *if_info, *ptr;
19486e91bba0SGirish Moodalbail show_if_args_t sargs;
19496e91bba0SGirish Moodalbail int option;
19506e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
19516e91bba0SGirish Moodalbail ofmt_status_t oferr;
19526e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
19536e91bba0SGirish Moodalbail char *ifname = NULL;
19546e91bba0SGirish Moodalbail
19556e91bba0SGirish Moodalbail opterr = 0;
19566e91bba0SGirish Moodalbail state.si_parsable = _B_FALSE;
19576e91bba0SGirish Moodalbail
19586e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, "po:", show_if_longopts,
19596e91bba0SGirish Moodalbail NULL)) != -1) {
19606e91bba0SGirish Moodalbail switch (option) {
19616e91bba0SGirish Moodalbail case 'p':
19626e91bba0SGirish Moodalbail state.si_parsable = _B_TRUE;
19636e91bba0SGirish Moodalbail break;
19646e91bba0SGirish Moodalbail case 'o':
19656e91bba0SGirish Moodalbail fields_str = optarg;
19666e91bba0SGirish Moodalbail break;
19676e91bba0SGirish Moodalbail default:
19686e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
19696e91bba0SGirish Moodalbail break;
19706e91bba0SGirish Moodalbail }
19716e91bba0SGirish Moodalbail }
19726e91bba0SGirish Moodalbail if (optind == argc - 1)
19736e91bba0SGirish Moodalbail ifname = argv[optind];
19746e91bba0SGirish Moodalbail else if (optind != argc)
19756e91bba0SGirish Moodalbail die("Usage: %s", use);
19766e91bba0SGirish Moodalbail if (state.si_parsable)
19776e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
19786e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
19796e91bba0SGirish Moodalbail ipadm_ofmt_check(oferr, state.si_parsable, ofmt);
19806e91bba0SGirish Moodalbail state.si_ofmt = ofmt;
19816e91bba0SGirish Moodalbail bzero(&sargs, sizeof (sargs));
19826e91bba0SGirish Moodalbail sargs.si_state = &state;
19836e91bba0SGirish Moodalbail status = ipadm_if_info(iph, ifname, &if_info, 0, LIFC_DEFAULT);
19846e91bba0SGirish Moodalbail /*
19856e91bba0SGirish Moodalbail * Return without printing any error, if no addresses were found.
19866e91bba0SGirish Moodalbail */
19876e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
19886e91bba0SGirish Moodalbail die("Could not get interface(s): %s",
19896e91bba0SGirish Moodalbail ipadm_status2str(status));
19906e91bba0SGirish Moodalbail }
19916e91bba0SGirish Moodalbail
19926e91bba0SGirish Moodalbail for (ptr = if_info; ptr; ptr = ptr->ifi_next) {
19936e91bba0SGirish Moodalbail sargs.si_info = ptr;
19946e91bba0SGirish Moodalbail ofmt_print(state.si_ofmt, &sargs);
19956e91bba0SGirish Moodalbail }
19966e91bba0SGirish Moodalbail if (if_info)
19976e91bba0SGirish Moodalbail ipadm_free_if_info(if_info);
19986e91bba0SGirish Moodalbail }
19996e91bba0SGirish Moodalbail
20006e91bba0SGirish Moodalbail /*
20016e91bba0SGirish Moodalbail * set/reset the address property for a given address
20026e91bba0SGirish Moodalbail */
20036e91bba0SGirish Moodalbail static void
set_addrprop(int argc,char ** argv,boolean_t reset,const char * use)20046e91bba0SGirish Moodalbail set_addrprop(int argc, char **argv, boolean_t reset, const char *use)
20056e91bba0SGirish Moodalbail {
20066e91bba0SGirish Moodalbail int option;
20076e91bba0SGirish Moodalbail ipadm_status_t status = IPADM_SUCCESS;
20086e91bba0SGirish Moodalbail boolean_t p_arg = _B_FALSE;
20096e91bba0SGirish Moodalbail char *nv, *aobjname;
20106e91bba0SGirish Moodalbail char *prop_name, *prop_val;
20116e91bba0SGirish Moodalbail uint_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
20126e91bba0SGirish Moodalbail
20136e91bba0SGirish Moodalbail opterr = 0;
20146e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":i:p:t", set_ifprop_longopts,
20156e91bba0SGirish Moodalbail NULL)) != -1) {
20166e91bba0SGirish Moodalbail switch (option) {
20176e91bba0SGirish Moodalbail case 'p':
20186e91bba0SGirish Moodalbail if (p_arg)
20196e91bba0SGirish Moodalbail die("-p must be specified once only");
20206e91bba0SGirish Moodalbail p_arg = _B_TRUE;
20216e91bba0SGirish Moodalbail
20226e91bba0SGirish Moodalbail ipadm_check_propstr(optarg, reset, use);
20236e91bba0SGirish Moodalbail nv = optarg;
20246e91bba0SGirish Moodalbail break;
20256e91bba0SGirish Moodalbail case 't':
20266e91bba0SGirish Moodalbail flags &= ~IPADM_OPT_PERSIST;
20276e91bba0SGirish Moodalbail break;
20286e91bba0SGirish Moodalbail default:
20296e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
20306e91bba0SGirish Moodalbail }
20316e91bba0SGirish Moodalbail }
20326e91bba0SGirish Moodalbail
20336e91bba0SGirish Moodalbail if (!p_arg || optind != (argc - 1))
20346e91bba0SGirish Moodalbail die("Usage: %s", use);
20356e91bba0SGirish Moodalbail
20366e91bba0SGirish Moodalbail prop_name = nv;
20376e91bba0SGirish Moodalbail prop_val = strchr(nv, '=');
20386e91bba0SGirish Moodalbail if (prop_val != NULL)
20396e91bba0SGirish Moodalbail *prop_val++ = '\0';
20406e91bba0SGirish Moodalbail aobjname = argv[optind];
20416e91bba0SGirish Moodalbail if (reset)
20426e91bba0SGirish Moodalbail flags |= IPADM_OPT_DEFAULT;
20436e91bba0SGirish Moodalbail status = ipadm_set_addrprop(iph, prop_name, prop_val, aobjname, flags);
20446e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
20456e91bba0SGirish Moodalbail if (reset)
20466e91bba0SGirish Moodalbail die("reset-addrprop: %s: %s", prop_name,
20476e91bba0SGirish Moodalbail ipadm_status2str(status));
20486e91bba0SGirish Moodalbail else
20496e91bba0SGirish Moodalbail die("set-addrprop: %s: %s", prop_name,
20506e91bba0SGirish Moodalbail ipadm_status2str(status));
20516e91bba0SGirish Moodalbail }
20526e91bba0SGirish Moodalbail }
20536e91bba0SGirish Moodalbail
20546e91bba0SGirish Moodalbail /*
20556e91bba0SGirish Moodalbail * Sets a property on an address object.
20566e91bba0SGirish Moodalbail */
20576e91bba0SGirish Moodalbail static void
do_set_addrprop(int argc,char ** argv,const char * use)20586e91bba0SGirish Moodalbail do_set_addrprop(int argc, char **argv, const char *use)
20596e91bba0SGirish Moodalbail {
20606e91bba0SGirish Moodalbail set_addrprop(argc, argv, _B_FALSE, use);
20616e91bba0SGirish Moodalbail }
20626e91bba0SGirish Moodalbail
20636e91bba0SGirish Moodalbail /*
20646e91bba0SGirish Moodalbail * Resets a property to its default value on an address object.
20656e91bba0SGirish Moodalbail */
20666e91bba0SGirish Moodalbail static void
do_reset_addrprop(int argc,char ** argv,const char * use)20676e91bba0SGirish Moodalbail do_reset_addrprop(int argc, char **argv, const char *use)
20686e91bba0SGirish Moodalbail {
20696e91bba0SGirish Moodalbail set_addrprop(argc, argv, _B_TRUE, use);
20706e91bba0SGirish Moodalbail }
20716e91bba0SGirish Moodalbail
20726e91bba0SGirish Moodalbail /*
20736e91bba0SGirish Moodalbail * Display information for all or specific address properties, either for a
20746e91bba0SGirish Moodalbail * given address or for all the addresses in the system.
20756e91bba0SGirish Moodalbail */
20766e91bba0SGirish Moodalbail static void
do_show_addrprop(int argc,char * argv[],const char * use)20776e91bba0SGirish Moodalbail do_show_addrprop(int argc, char *argv[], const char *use)
20786e91bba0SGirish Moodalbail {
20796e91bba0SGirish Moodalbail int option;
20806e91bba0SGirish Moodalbail nvlist_t *proplist = NULL;
20816e91bba0SGirish Moodalbail char *fields_str = NULL;
20826e91bba0SGirish Moodalbail show_prop_state_t state;
20836e91bba0SGirish Moodalbail ofmt_handle_t ofmt;
20846e91bba0SGirish Moodalbail ofmt_status_t oferr;
20856e91bba0SGirish Moodalbail uint_t ofmtflags = 0;
20866e91bba0SGirish Moodalbail char *aobjname;
20876e91bba0SGirish Moodalbail char *ifname = NULL;
20886e91bba0SGirish Moodalbail char *cp;
20896e91bba0SGirish Moodalbail
20906e91bba0SGirish Moodalbail opterr = 0;
20916e91bba0SGirish Moodalbail bzero(&state, sizeof (state));
20926e91bba0SGirish Moodalbail state.sps_propval = NULL;
20936e91bba0SGirish Moodalbail state.sps_parsable = _B_FALSE;
20946e91bba0SGirish Moodalbail state.sps_addrprop = _B_TRUE;
20956e91bba0SGirish Moodalbail state.sps_proto = MOD_PROTO_NONE;
20966e91bba0SGirish Moodalbail state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
20976e91bba0SGirish Moodalbail while ((option = getopt_long(argc, argv, ":p:i:cPo:",
20986e91bba0SGirish Moodalbail show_prop_longopts, NULL)) != -1) {
20996e91bba0SGirish Moodalbail switch (option) {
21006e91bba0SGirish Moodalbail case 'p':
21016e91bba0SGirish Moodalbail if (ipadm_str2nvlist(optarg, &proplist,
21026e91bba0SGirish Moodalbail IPADM_NORVAL) != 0)
21036e91bba0SGirish Moodalbail die("invalid interface properties specified");
21046e91bba0SGirish Moodalbail break;
21056e91bba0SGirish Moodalbail case 'c':
21066e91bba0SGirish Moodalbail state.sps_parsable = _B_TRUE;
21076e91bba0SGirish Moodalbail break;
21086e91bba0SGirish Moodalbail case 'o':
21096e91bba0SGirish Moodalbail fields_str = optarg;
21106e91bba0SGirish Moodalbail break;
21116e91bba0SGirish Moodalbail default:
21126e91bba0SGirish Moodalbail die_opterr(optopt, option, use);
21136e91bba0SGirish Moodalbail break;
21146e91bba0SGirish Moodalbail }
21156e91bba0SGirish Moodalbail }
21166e91bba0SGirish Moodalbail if (optind == argc - 1) {
21176e91bba0SGirish Moodalbail aobjname = argv[optind];
21186e91bba0SGirish Moodalbail cp = strchr(aobjname, '/');
21196e91bba0SGirish Moodalbail if (cp == NULL)
21206e91bba0SGirish Moodalbail die("Invalid address object name provided");
21216e91bba0SGirish Moodalbail if (*(cp + 1) == '\0') {
21226e91bba0SGirish Moodalbail ifname = aobjname;
21236e91bba0SGirish Moodalbail *cp = '\0';
21246e91bba0SGirish Moodalbail aobjname = NULL;
21256e91bba0SGirish Moodalbail }
21266e91bba0SGirish Moodalbail } else if (optind == argc) {
21276e91bba0SGirish Moodalbail aobjname = NULL;
21286e91bba0SGirish Moodalbail } else {
21296e91bba0SGirish Moodalbail die("Usage: %s", use);
21306e91bba0SGirish Moodalbail }
21316e91bba0SGirish Moodalbail state.sps_proplist = proplist;
21326e91bba0SGirish Moodalbail if (state.sps_parsable)
21336e91bba0SGirish Moodalbail ofmtflags |= OFMT_PARSABLE;
21346e91bba0SGirish Moodalbail oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
21356e91bba0SGirish Moodalbail ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
21366e91bba0SGirish Moodalbail state.sps_ofmt = ofmt;
21376e91bba0SGirish Moodalbail
21386e91bba0SGirish Moodalbail if (aobjname != NULL) {
21396e91bba0SGirish Moodalbail (void) strlcpy(state.sps_aobjname, aobjname,
21406e91bba0SGirish Moodalbail sizeof (state.sps_aobjname));
21416e91bba0SGirish Moodalbail show_properties(&state, IPADMPROP_CLASS_ADDR);
21426e91bba0SGirish Moodalbail } else {
21436e91bba0SGirish Moodalbail ipadm_addr_info_t *ainfop = NULL;
21446e91bba0SGirish Moodalbail ipadm_addr_info_t *ptr;
21456e91bba0SGirish Moodalbail ipadm_status_t status;
21466e91bba0SGirish Moodalbail
21476e91bba0SGirish Moodalbail status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
21486e91bba0SGirish Moodalbail /*
21496e91bba0SGirish Moodalbail * Return without printing any error, if no addresses were
21506e91bba0SGirish Moodalbail * found.
21516e91bba0SGirish Moodalbail */
21526e91bba0SGirish Moodalbail if (status == IPADM_NOTFOUND)
21536e91bba0SGirish Moodalbail return;
21546e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) {
21556e91bba0SGirish Moodalbail die("Error retrieving address: %s",
21566e91bba0SGirish Moodalbail ipadm_status2str(status));
21576e91bba0SGirish Moodalbail }
21586e91bba0SGirish Moodalbail for (ptr = ainfop; ptr; ptr = IA_NEXT(ptr)) {
21596e91bba0SGirish Moodalbail aobjname = ptr->ia_aobjname;
21606e91bba0SGirish Moodalbail if (aobjname[0] == '\0' ||
21616e91bba0SGirish Moodalbail ptr->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
21626e91bba0SGirish Moodalbail continue;
21636e91bba0SGirish Moodalbail }
21646e91bba0SGirish Moodalbail (void) strlcpy(state.sps_aobjname, aobjname,
21656e91bba0SGirish Moodalbail sizeof (state.sps_aobjname));
21666e91bba0SGirish Moodalbail show_properties(&state, IPADMPROP_CLASS_ADDR);
21676e91bba0SGirish Moodalbail }
21686e91bba0SGirish Moodalbail ipadm_free_addr_info(ainfop);
21696e91bba0SGirish Moodalbail }
21706e91bba0SGirish Moodalbail nvlist_free(proplist);
21716e91bba0SGirish Moodalbail ofmt_close(ofmt);
21726e91bba0SGirish Moodalbail if (state.sps_retstatus != IPADM_SUCCESS) {
21736e91bba0SGirish Moodalbail ipadm_close(iph);
21746e91bba0SGirish Moodalbail exit(EXIT_FAILURE);
21756e91bba0SGirish Moodalbail }
21766e91bba0SGirish Moodalbail }
21776e91bba0SGirish Moodalbail
21786e91bba0SGirish Moodalbail static void
ipadm_ofmt_check(ofmt_status_t oferr,boolean_t parsable,ofmt_handle_t ofmt)21796e91bba0SGirish Moodalbail ipadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
21806e91bba0SGirish Moodalbail ofmt_handle_t ofmt)
21816e91bba0SGirish Moodalbail {
21826e91bba0SGirish Moodalbail char buf[OFMT_BUFSIZE];
21836e91bba0SGirish Moodalbail
21846e91bba0SGirish Moodalbail if (oferr == OFMT_SUCCESS)
21856e91bba0SGirish Moodalbail return;
21866e91bba0SGirish Moodalbail (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
21876e91bba0SGirish Moodalbail /*
21886e91bba0SGirish Moodalbail * All errors are considered fatal in parsable mode.
21896e91bba0SGirish Moodalbail * NOMEM errors are always fatal, regardless of mode.
21906e91bba0SGirish Moodalbail * For other errors, we print diagnostics in human-readable
21916e91bba0SGirish Moodalbail * mode and processs what we can.
21926e91bba0SGirish Moodalbail */
21936e91bba0SGirish Moodalbail if (parsable || oferr == OFMT_ENOFIELDS) {
21946e91bba0SGirish Moodalbail ofmt_close(ofmt);
21956e91bba0SGirish Moodalbail die(buf);
21966e91bba0SGirish Moodalbail } else {
21976e91bba0SGirish Moodalbail warn(buf);
21986e91bba0SGirish Moodalbail }
21996e91bba0SGirish Moodalbail }
22006e91bba0SGirish Moodalbail
22016e91bba0SGirish Moodalbail /*
22026e91bba0SGirish Moodalbail * check if the `pstr' adheres to following syntax
22036e91bba0SGirish Moodalbail * - prop=<value[,...]> (for set)
22046e91bba0SGirish Moodalbail * - prop (for reset)
22056e91bba0SGirish Moodalbail */
22066e91bba0SGirish Moodalbail static void
ipadm_check_propstr(const char * pstr,boolean_t reset,const char * use)22076e91bba0SGirish Moodalbail ipadm_check_propstr(const char *pstr, boolean_t reset, const char *use)
22086e91bba0SGirish Moodalbail {
22096e91bba0SGirish Moodalbail char *nv;
22106e91bba0SGirish Moodalbail
22116e91bba0SGirish Moodalbail nv = strchr(pstr, '=');
22126e91bba0SGirish Moodalbail if (reset) {
22136e91bba0SGirish Moodalbail if (nv != NULL)
22146e91bba0SGirish Moodalbail die("incorrect syntax used for -p.\n%s", use);
22156e91bba0SGirish Moodalbail } else {
22166e91bba0SGirish Moodalbail if (nv == NULL || *++nv == '\0')
22176e91bba0SGirish Moodalbail die("please specify the value to be set.\n%s", use);
22186e91bba0SGirish Moodalbail nv = strchr(nv, '=');
22196e91bba0SGirish Moodalbail /* cannot have multiple 'prop=val' for single -p */
22206e91bba0SGirish Moodalbail if (nv != NULL)
22216e91bba0SGirish Moodalbail die("cannot specify more than one prop=val at "
22226e91bba0SGirish Moodalbail "a time.\n%s", use);
22236e91bba0SGirish Moodalbail }
22246e91bba0SGirish Moodalbail }
2225