17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54045d941Ssowmini * Common Development and Distribution License (the "License").
64045d941Ssowmini * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*8887b57dSGirish Moodalbail * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
24*8887b57dSGirish Moodalbail /* Copyright (c) 1990 Mentat Inc. */
257c478bd9Sstevel@tonic-gate
26*8887b57dSGirish Moodalbail #include <assert.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <errno.h>
297c478bd9Sstevel@tonic-gate #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <stdarg.h>
317c478bd9Sstevel@tonic-gate #include <fcntl.h>
327c478bd9Sstevel@tonic-gate #include <unistd.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <stropts.h>
356e91bba0SGirish Moodalbail #include <inet/tunables.h>
367c478bd9Sstevel@tonic-gate #include <inet/nd.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
386e91bba0SGirish Moodalbail #include <strings.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
404045d941Ssowmini #include <libdllink.h>
414045d941Ssowmini #include <libintl.h>
426e91bba0SGirish Moodalbail #include <libipadm.h>
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate static boolean_t do_getset(int fd, int cmd, char *buf, int buf_len);
457c478bd9Sstevel@tonic-gate static int get_value(char *msg, char *buf, int buf_len);
467c478bd9Sstevel@tonic-gate static void name_print(char *buf);
477c478bd9Sstevel@tonic-gate static void getset_interactive(int fd);
48a924b63fSVasumathi Sundaram - Sun Microsystems static int open_device(void);
497c478bd9Sstevel@tonic-gate static char *errmsg(int err);
507c478bd9Sstevel@tonic-gate static void fatal(char *fmt, ...);
517c478bd9Sstevel@tonic-gate static void printe(boolean_t print_errno, char *fmt, ...);
527c478bd9Sstevel@tonic-gate
536e91bba0SGirish Moodalbail static char modpath[128]; /* path to module */
546e91bba0SGirish Moodalbail static char gbuf[65536]; /* need large buffer to retrieve all names */
557c478bd9Sstevel@tonic-gate static char usage_str[] = "usage: ndd -set device_name name value\n"
567c478bd9Sstevel@tonic-gate " ndd [-get] device_name name [name ...]";
577c478bd9Sstevel@tonic-gate
58149b7eb2SSowmini Varadhan /*
596e91bba0SGirish Moodalbail * Maps old ndd_name to the new ipadm_name. Any ndd property that is moved to
606e91bba0SGirish Moodalbail * libipadm should have an entry here to ensure backward compatibility
616e91bba0SGirish Moodalbail */
626e91bba0SGirish Moodalbail typedef struct ndd2ipadm_map {
636e91bba0SGirish Moodalbail char *ndd_name;
646e91bba0SGirish Moodalbail char *ipadm_name;
656e91bba0SGirish Moodalbail uint_t ipadm_proto;
666e91bba0SGirish Moodalbail uint_t ipadm_flags;
676e91bba0SGirish Moodalbail uint_t ndd_perm;
686e91bba0SGirish Moodalbail } ndd2ipadm_map_t;
696e91bba0SGirish Moodalbail
706e91bba0SGirish Moodalbail static ndd2ipadm_map_t map[] = {
716e91bba0SGirish Moodalbail { "ip_def_ttl", "ttl", MOD_PROTO_IPV4, 0, 0 },
726e91bba0SGirish Moodalbail { "ip6_def_hops", "hoplimit", MOD_PROTO_IPV6, 0, 0 },
736e91bba0SGirish Moodalbail { "ip_forwarding", "forwarding", MOD_PROTO_IPV4, 0, 0 },
746e91bba0SGirish Moodalbail { "ip6_forwarding", "forwarding", MOD_PROTO_IPV6, 0, 0 },
756e91bba0SGirish Moodalbail { "icmp_recv_hiwat", "recv_maxbuf", MOD_PROTO_RAWIP, 0, 0 },
766e91bba0SGirish Moodalbail { "icmp_xmit_hiwat", "send_maxbuf", MOD_PROTO_RAWIP, 0, 0 },
776e91bba0SGirish Moodalbail { "tcp_ecn_permitted", "ecn", MOD_PROTO_TCP, 0, 0 },
786e91bba0SGirish Moodalbail { "tcp_extra_priv_ports_add", "extra_priv_ports", MOD_PROTO_TCP,
796e91bba0SGirish Moodalbail IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE },
806e91bba0SGirish Moodalbail { "tcp_extra_priv_ports_del", "extra_priv_ports", MOD_PROTO_TCP,
816e91bba0SGirish Moodalbail IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE },
826e91bba0SGirish Moodalbail { "tcp_extra_priv_ports", "extra_priv_ports", MOD_PROTO_TCP,
836e91bba0SGirish Moodalbail 0, MOD_PROP_PERM_READ },
846e91bba0SGirish Moodalbail { "tcp_largest_anon_port", "largest_anon_port", MOD_PROTO_TCP,
856e91bba0SGirish Moodalbail 0, 0 },
866e91bba0SGirish Moodalbail { "tcp_recv_hiwat", "recv_maxbuf", MOD_PROTO_TCP, 0, 0 },
876e91bba0SGirish Moodalbail { "tcp_sack_permitted", "sack", MOD_PROTO_TCP, 0, 0 },
886e91bba0SGirish Moodalbail { "tcp_xmit_hiwat", "send_maxbuf", MOD_PROTO_TCP, 0, 0 },
896e91bba0SGirish Moodalbail { "tcp_smallest_anon_port", "smallest_anon_port", MOD_PROTO_TCP,
906e91bba0SGirish Moodalbail 0, 0 },
916e91bba0SGirish Moodalbail { "tcp_smallest_nonpriv_port", "smallest_nonpriv_port", MOD_PROTO_TCP,
926e91bba0SGirish Moodalbail 0, 0 },
936e91bba0SGirish Moodalbail { "udp_extra_priv_ports_add", "extra_priv_ports", MOD_PROTO_UDP,
946e91bba0SGirish Moodalbail IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE },
956e91bba0SGirish Moodalbail { "udp_extra_priv_ports_del", "extra_priv_ports", MOD_PROTO_UDP,
966e91bba0SGirish Moodalbail IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE },
976e91bba0SGirish Moodalbail { "udp_extra_priv_ports", "extra_priv_ports", MOD_PROTO_UDP,
986e91bba0SGirish Moodalbail 0, MOD_PROP_PERM_READ },
996e91bba0SGirish Moodalbail { "udp_largest_anon_port", "largest_anon_port", MOD_PROTO_UDP,
1006e91bba0SGirish Moodalbail 0, 0 },
1016e91bba0SGirish Moodalbail { "udp_recv_hiwat", "recv_maxbuf", MOD_PROTO_UDP, 0, 0 },
1026e91bba0SGirish Moodalbail { "udp_xmit_hiwat", "send_maxbuf", MOD_PROTO_UDP, 0, 0 },
1036e91bba0SGirish Moodalbail { "udp_smallest_anon_port", "smallest_anon_port", MOD_PROTO_UDP,
1046e91bba0SGirish Moodalbail 0, 0 },
1056e91bba0SGirish Moodalbail { "udp_smallest_nonpriv_port", "smallest_nonpriv_port", MOD_PROTO_UDP,
1066e91bba0SGirish Moodalbail 0, 0 },
1076e91bba0SGirish Moodalbail { "sctp_extra_priv_ports_add", "extra_priv_ports", MOD_PROTO_SCTP,
1086e91bba0SGirish Moodalbail IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE },
1096e91bba0SGirish Moodalbail { "sctp_extra_priv_ports_del", "extra_priv_ports", MOD_PROTO_SCTP,
1106e91bba0SGirish Moodalbail IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE },
1116e91bba0SGirish Moodalbail { "sctp_extra_priv_ports", "extra_priv_ports", MOD_PROTO_SCTP,
1126e91bba0SGirish Moodalbail 0, MOD_PROP_PERM_READ },
1136e91bba0SGirish Moodalbail { "sctp_largest_anon_port", "largest_anon_port", MOD_PROTO_SCTP,
1146e91bba0SGirish Moodalbail 0, 0 },
1156e91bba0SGirish Moodalbail { "sctp_recv_hiwat", "recv_maxbuf", MOD_PROTO_SCTP, 0, 0 },
1166e91bba0SGirish Moodalbail { "sctp_xmit_hiwat", "send_maxbuf", MOD_PROTO_SCTP, 0, 0 },
1176e91bba0SGirish Moodalbail { "sctp_smallest_anon_port", "smallest_anon_port", MOD_PROTO_SCTP,
1186e91bba0SGirish Moodalbail 0, 0 },
1196e91bba0SGirish Moodalbail { "sctp_smallest_nonpriv_port", "smallest_nonpriv_port", MOD_PROTO_SCTP,
1206e91bba0SGirish Moodalbail 0, 0 },
1216e91bba0SGirish Moodalbail { NULL, NULL, 0, 0, 0 }
1226e91bba0SGirish Moodalbail };
1236e91bba0SGirish Moodalbail
1246e91bba0SGirish Moodalbail static uint_t
ndd_str2proto(const char * protostr)1256e91bba0SGirish Moodalbail ndd_str2proto(const char *protostr)
1266e91bba0SGirish Moodalbail {
1276e91bba0SGirish Moodalbail if (strcmp(protostr, "tcp") == 0 ||
1286e91bba0SGirish Moodalbail strcmp(protostr, "tcp6") == 0) {
1296e91bba0SGirish Moodalbail return (MOD_PROTO_TCP);
1306e91bba0SGirish Moodalbail } else if (strcmp(protostr, "udp") == 0 ||
1316e91bba0SGirish Moodalbail strcmp(protostr, "udp6") == 0) {
1326e91bba0SGirish Moodalbail return (MOD_PROTO_UDP);
1336e91bba0SGirish Moodalbail } else if (strcmp(protostr, "ip") == 0 ||
1346e91bba0SGirish Moodalbail strcmp(protostr, "ip6") == 0 ||
1356e91bba0SGirish Moodalbail strcmp(protostr, "arp") == 0) {
1366e91bba0SGirish Moodalbail return (MOD_PROTO_IP);
1376e91bba0SGirish Moodalbail } else if (strcmp(protostr, "icmp") == 0 ||
1386e91bba0SGirish Moodalbail strcmp(protostr, "icmp6") == 0) {
1396e91bba0SGirish Moodalbail return (MOD_PROTO_RAWIP);
1406e91bba0SGirish Moodalbail } else if (strcmp(protostr, "sctp") == 0 ||
1416e91bba0SGirish Moodalbail strcmp(protostr, "sctp6") == 0) {
1426e91bba0SGirish Moodalbail return (MOD_PROTO_SCTP);
1436e91bba0SGirish Moodalbail }
1446e91bba0SGirish Moodalbail return (MOD_PROTO_NONE);
1456e91bba0SGirish Moodalbail }
1466e91bba0SGirish Moodalbail
1476e91bba0SGirish Moodalbail static char *
ndd_perm2str(uint_t perm)1486e91bba0SGirish Moodalbail ndd_perm2str(uint_t perm)
1496e91bba0SGirish Moodalbail {
1506e91bba0SGirish Moodalbail switch (perm) {
1516e91bba0SGirish Moodalbail case MOD_PROP_PERM_READ:
1526e91bba0SGirish Moodalbail return ("read only");
1536e91bba0SGirish Moodalbail case MOD_PROP_PERM_WRITE:
1546e91bba0SGirish Moodalbail return ("write only");
1556e91bba0SGirish Moodalbail case MOD_PROP_PERM_RW:
1566e91bba0SGirish Moodalbail return ("read and write");
1576e91bba0SGirish Moodalbail }
1586e91bba0SGirish Moodalbail
1596e91bba0SGirish Moodalbail return (NULL);
1606e91bba0SGirish Moodalbail }
1616e91bba0SGirish Moodalbail
1626e91bba0SGirish Moodalbail /*
163*8887b57dSGirish Moodalbail * Print all the protocol properties for the given protocol name. The kernel
164*8887b57dSGirish Moodalbail * returns all the properties for the given protocol therefore we have to
165*8887b57dSGirish Moodalbail * apply some filters before we print them.
166*8887b57dSGirish Moodalbail *
167*8887b57dSGirish Moodalbail * - convert any new ipadm name to old ndd name using the table.
168*8887b57dSGirish Moodalbail * For example: `sack' --> `tcp_sack_permitted'.
169*8887b57dSGirish Moodalbail *
170*8887b57dSGirish Moodalbail * - replace leading underscores with protocol name.
171*8887b57dSGirish Moodalbail * For example: `_strong_iss' --> `tcp_strong_iss'
172*8887b57dSGirish Moodalbail *
173*8887b57dSGirish Moodalbail * - don't print new public properties that are supported only by ipadm(1M)
174*8887b57dSGirish Moodalbail * For example: `hostmodel' should be supported only from ipadm(1M).
175*8887b57dSGirish Moodalbail * Such properties are identified by not having leading '_' and not
176*8887b57dSGirish Moodalbail * being present in the mapping table.
1776e91bba0SGirish Moodalbail */
1786e91bba0SGirish Moodalbail static void
print_ipadm2ndd(char * oldbuf,uint_t obufsize)1796e91bba0SGirish Moodalbail print_ipadm2ndd(char *oldbuf, uint_t obufsize)
1806e91bba0SGirish Moodalbail {
1816e91bba0SGirish Moodalbail ndd2ipadm_map_t *nimap;
1826e91bba0SGirish Moodalbail char *pname, *rwtag, *protostr;
1836e91bba0SGirish Moodalbail uint_t proto, perm;
1846e91bba0SGirish Moodalbail boolean_t matched;
1856e91bba0SGirish Moodalbail
1866e91bba0SGirish Moodalbail pname = oldbuf;
1876e91bba0SGirish Moodalbail while (pname[0] && pname < (oldbuf + obufsize - 1)) {
1886e91bba0SGirish Moodalbail for (protostr = pname; !isspace(*protostr); protostr++)
1896e91bba0SGirish Moodalbail ;
1906e91bba0SGirish Moodalbail *protostr++ = '\0';
1916e91bba0SGirish Moodalbail /* protostr now points to protocol */
1926e91bba0SGirish Moodalbail
1936e91bba0SGirish Moodalbail for (rwtag = protostr; !isspace(*rwtag); rwtag++)
1946e91bba0SGirish Moodalbail ;
1956e91bba0SGirish Moodalbail *rwtag++ = '\0';
1966e91bba0SGirish Moodalbail /* rwtag now points to permissions */
1976e91bba0SGirish Moodalbail
1986e91bba0SGirish Moodalbail proto = atoi(protostr);
1996e91bba0SGirish Moodalbail perm = atoi(rwtag);
2006e91bba0SGirish Moodalbail matched = B_FALSE;
2016e91bba0SGirish Moodalbail for (nimap = map; nimap->ndd_name != NULL; nimap++) {
2026e91bba0SGirish Moodalbail if (strcmp(pname, nimap->ipadm_name) != 0 ||
2036e91bba0SGirish Moodalbail !(nimap->ipadm_proto & proto))
2046e91bba0SGirish Moodalbail continue;
2056e91bba0SGirish Moodalbail
2066e91bba0SGirish Moodalbail matched = B_TRUE;
2076e91bba0SGirish Moodalbail if (nimap->ndd_perm != 0)
2086e91bba0SGirish Moodalbail perm = nimap->ndd_perm;
2096e91bba0SGirish Moodalbail (void) printf("%-30s (%s)\n", nimap->ndd_name,
2106e91bba0SGirish Moodalbail ndd_perm2str(perm));
2116e91bba0SGirish Moodalbail }
212*8887b57dSGirish Moodalbail /*
213*8887b57dSGirish Moodalbail * print only if it's a private property. We should
214*8887b57dSGirish Moodalbail * not be printing any new public property in ndd(1M)
215*8887b57dSGirish Moodalbail * output.
216*8887b57dSGirish Moodalbail */
217*8887b57dSGirish Moodalbail if (!matched && pname[0] == '_') {
218*8887b57dSGirish Moodalbail char tmpstr[512];
219*8887b57dSGirish Moodalbail int err;
220*8887b57dSGirish Moodalbail
221*8887b57dSGirish Moodalbail err = ipadm_new2legacy_propname(pname, tmpstr,
222*8887b57dSGirish Moodalbail sizeof (tmpstr), proto);
223*8887b57dSGirish Moodalbail assert(err != -1);
224*8887b57dSGirish Moodalbail
225*8887b57dSGirish Moodalbail (void) printf("%-30s (%s)\n", tmpstr,
2266e91bba0SGirish Moodalbail ndd_perm2str(perm));
227*8887b57dSGirish Moodalbail }
2286e91bba0SGirish Moodalbail for (pname = rwtag; *pname++; )
2296e91bba0SGirish Moodalbail ;
2306e91bba0SGirish Moodalbail }
2316e91bba0SGirish Moodalbail }
2326e91bba0SGirish Moodalbail
2336e91bba0SGirish Moodalbail /*
2346e91bba0SGirish Moodalbail * get/set the value for a given property by calling into libipadm. The
2356e91bba0SGirish Moodalbail * IPH_LEGACY flag is used by libipadm for special handling. For some
2366e91bba0SGirish Moodalbail * properties, libipadm.so displays strings (for e.g., on/off,
2376e91bba0SGirish Moodalbail * never/passive/active, et al) instead of numerals. However ndd(1M) always
2386e91bba0SGirish Moodalbail * printed numberals. This flag will help in avoiding printing strings.
2396e91bba0SGirish Moodalbail */
2406e91bba0SGirish Moodalbail static boolean_t
do_ipadm_getset(int cmd,char * buf,int buflen)2416e91bba0SGirish Moodalbail do_ipadm_getset(int cmd, char *buf, int buflen)
2426e91bba0SGirish Moodalbail {
2436e91bba0SGirish Moodalbail ndd2ipadm_map_t *nimap;
2446e91bba0SGirish Moodalbail ipadm_handle_t iph = NULL;
2456e91bba0SGirish Moodalbail ipadm_status_t status;
2466e91bba0SGirish Moodalbail char *mod;
2476e91bba0SGirish Moodalbail uint_t proto, perm = 0, flags = 0;
248*8887b57dSGirish Moodalbail char *pname, *pvalp, nname[512];
2496e91bba0SGirish Moodalbail int i;
2506e91bba0SGirish Moodalbail
2516e91bba0SGirish Moodalbail if ((mod = strrchr(modpath, '/')) == NULL)
2526e91bba0SGirish Moodalbail mod = modpath;
2536e91bba0SGirish Moodalbail else
2546e91bba0SGirish Moodalbail ++mod;
2556e91bba0SGirish Moodalbail if ((proto = ndd_str2proto(mod)) == MOD_PROTO_NONE)
2566e91bba0SGirish Moodalbail return (B_FALSE);
2576e91bba0SGirish Moodalbail
2586e91bba0SGirish Moodalbail if ((status = ipadm_open(&iph, IPH_LEGACY)) != IPADM_SUCCESS)
2596e91bba0SGirish Moodalbail goto fail;
2606e91bba0SGirish Moodalbail
2616e91bba0SGirish Moodalbail pname = buf;
2626e91bba0SGirish Moodalbail for (nimap = map; nimap->ndd_name != NULL; nimap++) {
263*8887b57dSGirish Moodalbail if (strcmp(pname, nimap->ndd_name) == 0) {
2646e91bba0SGirish Moodalbail pname = nimap->ipadm_name;
2656e91bba0SGirish Moodalbail proto = nimap->ipadm_proto;
2666e91bba0SGirish Moodalbail flags = nimap->ipadm_flags;
2676e91bba0SGirish Moodalbail perm = nimap->ndd_perm;
268*8887b57dSGirish Moodalbail break;
2696e91bba0SGirish Moodalbail }
270*8887b57dSGirish Moodalbail }
271*8887b57dSGirish Moodalbail
272*8887b57dSGirish Moodalbail if (nimap->ndd_name == NULL && strcmp(pname, "?") != 0) {
273*8887b57dSGirish Moodalbail /* do not allow set/get of public properties from ndd(1M) */
274*8887b57dSGirish Moodalbail if (ipadm_legacy2new_propname(pname, nname, sizeof (nname),
275*8887b57dSGirish Moodalbail &proto) != 0) {
276*8887b57dSGirish Moodalbail status = IPADM_PROP_UNKNOWN;
277*8887b57dSGirish Moodalbail goto fail;
278*8887b57dSGirish Moodalbail } else {
279*8887b57dSGirish Moodalbail pname = nname;
280*8887b57dSGirish Moodalbail }
281*8887b57dSGirish Moodalbail }
282*8887b57dSGirish Moodalbail
2836e91bba0SGirish Moodalbail if (cmd == ND_GET) {
2846e91bba0SGirish Moodalbail char propval[MAXPROPVALLEN], allprop[64536];
2856e91bba0SGirish Moodalbail uint_t pvalsz;
2866e91bba0SGirish Moodalbail sa_family_t af = AF_UNSPEC;
2876e91bba0SGirish Moodalbail int err;
2886e91bba0SGirish Moodalbail
2896e91bba0SGirish Moodalbail if (perm == MOD_PROP_PERM_WRITE)
2906e91bba0SGirish Moodalbail fatal("operation failed: Permission denied");
2916e91bba0SGirish Moodalbail
2926e91bba0SGirish Moodalbail if (strcmp(pname, "?") == 0) {
2936e91bba0SGirish Moodalbail pvalp = allprop;
2946e91bba0SGirish Moodalbail pvalsz = sizeof (allprop);
2956e91bba0SGirish Moodalbail } else {
2966e91bba0SGirish Moodalbail pvalp = propval;
2976e91bba0SGirish Moodalbail pvalsz = sizeof (propval);
2986e91bba0SGirish Moodalbail }
2996e91bba0SGirish Moodalbail
3006e91bba0SGirish Moodalbail status = ipadm_get_prop(iph, pname, pvalp, &pvalsz, proto,
3016e91bba0SGirish Moodalbail IPADM_OPT_ACTIVE);
3026e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
3036e91bba0SGirish Moodalbail goto fail;
3046e91bba0SGirish Moodalbail
3056e91bba0SGirish Moodalbail if (strcmp(pname, "?") == 0) {
3066e91bba0SGirish Moodalbail (void) print_ipadm2ndd(pvalp, pvalsz);
3076e91bba0SGirish Moodalbail } else {
3086e91bba0SGirish Moodalbail char *tmp = pvalp;
3096e91bba0SGirish Moodalbail
3106e91bba0SGirish Moodalbail /*
3116e91bba0SGirish Moodalbail * For backward compatibility if there are multiple
3126e91bba0SGirish Moodalbail * values print each value in it's own line.
3136e91bba0SGirish Moodalbail */
3146e91bba0SGirish Moodalbail while (*tmp != '\0') {
3156e91bba0SGirish Moodalbail if (*tmp == ',')
3166e91bba0SGirish Moodalbail *tmp = '\n';
3176e91bba0SGirish Moodalbail tmp++;
3186e91bba0SGirish Moodalbail }
3196e91bba0SGirish Moodalbail (void) printf("%s\n", pvalp);
3206e91bba0SGirish Moodalbail }
3216e91bba0SGirish Moodalbail (void) fflush(stdout);
3226e91bba0SGirish Moodalbail } else {
3236e91bba0SGirish Moodalbail if (perm == MOD_PROP_PERM_READ)
3246e91bba0SGirish Moodalbail fatal("operation failed: Permission denied");
3256e91bba0SGirish Moodalbail
3266e91bba0SGirish Moodalbail /* walk past the property name to find the property value */
3276e91bba0SGirish Moodalbail for (i = 0; buf[i] != '\0'; i++)
3286e91bba0SGirish Moodalbail ;
3296e91bba0SGirish Moodalbail
3306e91bba0SGirish Moodalbail pvalp = &buf[++i];
3316e91bba0SGirish Moodalbail status = ipadm_set_prop(iph, pname, pvalp, proto,
3326e91bba0SGirish Moodalbail flags|IPADM_OPT_ACTIVE);
3336e91bba0SGirish Moodalbail }
3346e91bba0SGirish Moodalbail fail:
3356e91bba0SGirish Moodalbail ipadm_close(iph);
3366e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS)
3376e91bba0SGirish Moodalbail fatal("operation failed: %s", ipadm_status2str(status));
3386e91bba0SGirish Moodalbail return (B_TRUE);
3396e91bba0SGirish Moodalbail }
3406e91bba0SGirish Moodalbail
3416e91bba0SGirish Moodalbail /*
342149b7eb2SSowmini Varadhan * gldv3_warning() catches the case of /sbin/ndd abuse to administer
343149b7eb2SSowmini Varadhan * ethernet/MII props. Note that /sbin/ndd has not been abused
344149b7eb2SSowmini Varadhan * for administration of other datalink types, which makes it permissible
345149b7eb2SSowmini Varadhan * to test for support of the flowctrl property.
346149b7eb2SSowmini Varadhan */
3474045d941Ssowmini static void
gldv3_warning(char * module)348a924b63fSVasumathi Sundaram - Sun Microsystems gldv3_warning(char *module)
3494045d941Ssowmini {
3504045d941Ssowmini datalink_id_t linkid;
3514045d941Ssowmini dladm_status_t status;
3524045d941Ssowmini char buf[DLADM_PROP_VAL_MAX], *cp;
353149b7eb2SSowmini Varadhan uint_t cnt = 1;
3544045d941Ssowmini char *link;
355a924b63fSVasumathi Sundaram - Sun Microsystems dladm_handle_t handle;
3564045d941Ssowmini
3574045d941Ssowmini link = strrchr(module, '/');
3584045d941Ssowmini if (link == NULL)
3594045d941Ssowmini return;
360a924b63fSVasumathi Sundaram - Sun Microsystems
361a924b63fSVasumathi Sundaram - Sun Microsystems if (dladm_open(&handle) != DLADM_STATUS_OK)
362a924b63fSVasumathi Sundaram - Sun Microsystems return;
363a924b63fSVasumathi Sundaram - Sun Microsystems
3644ac67f02SAnurag S. Maskey status = dladm_name2info(handle, ++link, &linkid, NULL, NULL, NULL);
365a924b63fSVasumathi Sundaram - Sun Microsystems if (status == DLADM_STATUS_OK) {
3664045d941Ssowmini cp = buf;
367a924b63fSVasumathi Sundaram - Sun Microsystems status = dladm_get_linkprop(handle, linkid,
368a924b63fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_CURRENT, "flowctrl", &cp, &cnt);
369a924b63fSVasumathi Sundaram - Sun Microsystems if (status == DLADM_STATUS_OK) {
3704045d941Ssowmini (void) fprintf(stderr, gettext(
371a924b63fSVasumathi Sundaram - Sun Microsystems "WARNING: The ndd commands for datalink "
372a924b63fSVasumathi Sundaram - Sun Microsystems "administration are obsolete and may be "
373a924b63fSVasumathi Sundaram - Sun Microsystems "removed in a future release of Solaris. "
374a924b63fSVasumathi Sundaram - Sun Microsystems "Use dladm(1M) to manage datalink tunables.\n"));
375a924b63fSVasumathi Sundaram - Sun Microsystems }
376a924b63fSVasumathi Sundaram - Sun Microsystems }
377a924b63fSVasumathi Sundaram - Sun Microsystems dladm_close(handle);
3784045d941Ssowmini }
3794045d941Ssowmini
3807c478bd9Sstevel@tonic-gate /* ARGSUSED */
3817c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)3827c478bd9Sstevel@tonic-gate main(int argc, char **argv)
3837c478bd9Sstevel@tonic-gate {
3846e91bba0SGirish Moodalbail char *cp, *value, *mod;
3857c478bd9Sstevel@tonic-gate int cmd;
3866e91bba0SGirish Moodalbail int fd = 0;
3874045d941Ssowmini
3887c478bd9Sstevel@tonic-gate if (!(cp = *++argv)) {
389a924b63fSVasumathi Sundaram - Sun Microsystems while ((fd = open_device()) != -1) {
3907c478bd9Sstevel@tonic-gate getset_interactive(fd);
3917c478bd9Sstevel@tonic-gate (void) close(fd);
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate return (EXIT_SUCCESS);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate cmd = ND_GET;
3977c478bd9Sstevel@tonic-gate if (cp[0] == '-') {
3987c478bd9Sstevel@tonic-gate if (strncmp(&cp[1], "set", 3) == 0)
3997c478bd9Sstevel@tonic-gate cmd = ND_SET;
4007c478bd9Sstevel@tonic-gate else if (strncmp(&cp[1], "get", 3) != 0)
4017c478bd9Sstevel@tonic-gate fatal(usage_str);
4027c478bd9Sstevel@tonic-gate if (!(cp = *++argv))
4037c478bd9Sstevel@tonic-gate fatal(usage_str);
4047c478bd9Sstevel@tonic-gate }
4056e91bba0SGirish Moodalbail
406a924b63fSVasumathi Sundaram - Sun Microsystems gldv3_warning(cp);
4074ac67f02SAnurag S. Maskey
4086e91bba0SGirish Moodalbail mod = strrchr(cp, '/');
4096e91bba0SGirish Moodalbail if (mod != NULL)
4106e91bba0SGirish Moodalbail mod++;
4116e91bba0SGirish Moodalbail else
4126e91bba0SGirish Moodalbail mod = cp;
4136e91bba0SGirish Moodalbail
4146e91bba0SGirish Moodalbail if (ndd_str2proto(mod) == MOD_PROTO_NONE) {
4157c478bd9Sstevel@tonic-gate if ((fd = open(cp, O_RDWR)) == -1)
4167c478bd9Sstevel@tonic-gate fatal("open of %s failed: %s", cp, errmsg(errno));
4177c478bd9Sstevel@tonic-gate if (!isastream(fd))
4187c478bd9Sstevel@tonic-gate fatal("%s is not a streams device", cp);
4196e91bba0SGirish Moodalbail }
4207c478bd9Sstevel@tonic-gate
4216e91bba0SGirish Moodalbail (void) strlcpy(modpath, cp, sizeof (modpath));
4227c478bd9Sstevel@tonic-gate if (!(cp = *++argv)) {
4237c478bd9Sstevel@tonic-gate getset_interactive(fd);
4247c478bd9Sstevel@tonic-gate (void) close(fd);
4257c478bd9Sstevel@tonic-gate return (EXIT_SUCCESS);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate if (cmd == ND_SET) {
4297c478bd9Sstevel@tonic-gate if (!(value = *++argv))
4307c478bd9Sstevel@tonic-gate fatal(usage_str);
4317c478bd9Sstevel@tonic-gate (void) snprintf(gbuf, sizeof (gbuf), "%s%c%s%c", cp, '\0',
4327c478bd9Sstevel@tonic-gate value, '\0');
4337c478bd9Sstevel@tonic-gate if (!do_getset(fd, cmd, gbuf, sizeof (gbuf)))
4347c478bd9Sstevel@tonic-gate return (EXIT_FAILURE);
4357c478bd9Sstevel@tonic-gate } else {
4367c478bd9Sstevel@tonic-gate do {
4377c478bd9Sstevel@tonic-gate (void) memset(gbuf, '\0', sizeof (gbuf));
4387c478bd9Sstevel@tonic-gate (void) strlcpy(gbuf, cp, sizeof (gbuf));
4397c478bd9Sstevel@tonic-gate if (!do_getset(fd, cmd, gbuf, sizeof (gbuf)))
4407c478bd9Sstevel@tonic-gate return (EXIT_FAILURE);
4417c478bd9Sstevel@tonic-gate if (cp = *++argv)
4427c478bd9Sstevel@tonic-gate (void) putchar('\n');
4437c478bd9Sstevel@tonic-gate } while (cp);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate (void) close(fd);
4477c478bd9Sstevel@tonic-gate return (EXIT_SUCCESS);
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate static void
name_print(char * buf)4517c478bd9Sstevel@tonic-gate name_print(char *buf)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate char *cp, *rwtag;
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate for (cp = buf; cp[0]; ) {
4567c478bd9Sstevel@tonic-gate for (rwtag = cp; !isspace(*rwtag); rwtag++)
4577c478bd9Sstevel@tonic-gate ;
4587c478bd9Sstevel@tonic-gate *rwtag++ = '\0';
4597c478bd9Sstevel@tonic-gate while (isspace(*rwtag))
4607c478bd9Sstevel@tonic-gate rwtag++;
4617c478bd9Sstevel@tonic-gate (void) printf("%-30s%s\n", cp, rwtag);
4627c478bd9Sstevel@tonic-gate for (cp = rwtag; *cp++; )
4637c478bd9Sstevel@tonic-gate ;
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate /*
4687c478bd9Sstevel@tonic-gate * This function is vile, but it's better here than in the kernel.
4697c478bd9Sstevel@tonic-gate */
4707c478bd9Sstevel@tonic-gate static boolean_t
is_obsolete(const char * param)4717c478bd9Sstevel@tonic-gate is_obsolete(const char *param)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate if (strcmp(param, "ip_enable_group_ifs") == 0 ||
4747c478bd9Sstevel@tonic-gate strcmp(param, "ifgrp_status") == 0) {
4757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "The \"%s\" tunable has been superseded "
4767c478bd9Sstevel@tonic-gate "by IP Multipathing.\nPlease see the IP Network "
4777c478bd9Sstevel@tonic-gate "Multipathing Administration Guide for details.\n", param);
4787c478bd9Sstevel@tonic-gate return (B_TRUE);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate return (B_FALSE);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate static boolean_t
do_getset(int fd,int cmd,char * buf,int buf_len)4847c478bd9Sstevel@tonic-gate do_getset(int fd, int cmd, char *buf, int buf_len)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate char *cp;
4877c478bd9Sstevel@tonic-gate struct strioctl stri;
4887c478bd9Sstevel@tonic-gate boolean_t is_name_get;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate if (is_obsolete(buf))
4917c478bd9Sstevel@tonic-gate return (B_TRUE);
4927c478bd9Sstevel@tonic-gate
4936e91bba0SGirish Moodalbail /*
4946e91bba0SGirish Moodalbail * See if libipadm can handle this request, i.e., properties on
4956e91bba0SGirish Moodalbail * following modules arp, ip, ipv4, ipv6, tcp, udp and sctp
4966e91bba0SGirish Moodalbail */
4976e91bba0SGirish Moodalbail if (do_ipadm_getset(cmd, buf, buf_len))
4986e91bba0SGirish Moodalbail return (B_TRUE);
4996e91bba0SGirish Moodalbail
5007c478bd9Sstevel@tonic-gate stri.ic_cmd = cmd;
5017c478bd9Sstevel@tonic-gate stri.ic_timout = 0;
5027c478bd9Sstevel@tonic-gate stri.ic_len = buf_len;
5037c478bd9Sstevel@tonic-gate stri.ic_dp = buf;
5047c478bd9Sstevel@tonic-gate is_name_get = stri.ic_cmd == ND_GET && buf[0] == '?' && buf[1] == '\0';
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate if (ioctl(fd, I_STR, &stri) == -1) {
5077c478bd9Sstevel@tonic-gate if (errno == ENOENT)
5087c478bd9Sstevel@tonic-gate (void) printf("name is non-existent for this module\n"
5097c478bd9Sstevel@tonic-gate "for a list of valid names, use name '?'\n");
5107c478bd9Sstevel@tonic-gate else
5117c478bd9Sstevel@tonic-gate (void) printf("operation failed: %s\n", errmsg(errno));
5127c478bd9Sstevel@tonic-gate return (B_FALSE);
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate if (is_name_get)
5157c478bd9Sstevel@tonic-gate name_print(buf);
5167c478bd9Sstevel@tonic-gate else if (stri.ic_cmd == ND_GET) {
5177c478bd9Sstevel@tonic-gate for (cp = buf; *cp != '\0'; cp += strlen(cp) + 1)
5187c478bd9Sstevel@tonic-gate (void) puts(cp);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate (void) fflush(stdout);
5217c478bd9Sstevel@tonic-gate return (B_TRUE);
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate static int
get_value(char * msg,char * buf,int buf_len)5257c478bd9Sstevel@tonic-gate get_value(char *msg, char *buf, int buf_len)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate int len;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate (void) printf("%s", msg);
5307c478bd9Sstevel@tonic-gate (void) fflush(stdout);
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate buf[buf_len-1] = '\0';
5337c478bd9Sstevel@tonic-gate if (fgets(buf, buf_len-1, stdin) == NULL)
5347c478bd9Sstevel@tonic-gate exit(EXIT_SUCCESS);
5357c478bd9Sstevel@tonic-gate len = strlen(buf);
5367c478bd9Sstevel@tonic-gate if (buf[len-1] == '\n')
5377c478bd9Sstevel@tonic-gate buf[len - 1] = '\0';
5387c478bd9Sstevel@tonic-gate else
5397c478bd9Sstevel@tonic-gate len++;
5407c478bd9Sstevel@tonic-gate return (len);
5417c478bd9Sstevel@tonic-gate }
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate static void
getset_interactive(int fd)5447c478bd9Sstevel@tonic-gate getset_interactive(int fd)
5457c478bd9Sstevel@tonic-gate {
5467c478bd9Sstevel@tonic-gate int cmd;
5477c478bd9Sstevel@tonic-gate char *cp;
5487c478bd9Sstevel@tonic-gate int len, buf_len;
5497c478bd9Sstevel@tonic-gate char len_buf[10];
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate for (;;) {
5527c478bd9Sstevel@tonic-gate (void) memset(gbuf, '\0', sizeof (gbuf));
5537c478bd9Sstevel@tonic-gate len = get_value("name to get/set ? ", gbuf, sizeof (gbuf));
5547c478bd9Sstevel@tonic-gate if (len == 1 || (gbuf[0] == 'q' && gbuf[1] == '\0'))
5557c478bd9Sstevel@tonic-gate return;
5567c478bd9Sstevel@tonic-gate for (cp = gbuf; cp < &gbuf[len]; cp++) {
5577c478bd9Sstevel@tonic-gate if (isspace(*cp))
5587c478bd9Sstevel@tonic-gate *cp = '\0';
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate cmd = ND_GET;
5617c478bd9Sstevel@tonic-gate if (gbuf[0] != '?' &&
5627c478bd9Sstevel@tonic-gate get_value("value ? ", &gbuf[len], sizeof (gbuf) - len) > 1)
5637c478bd9Sstevel@tonic-gate cmd = ND_SET;
5647c478bd9Sstevel@tonic-gate if (cmd == ND_GET && gbuf[0] != '?' &&
5657c478bd9Sstevel@tonic-gate get_value("length ? ", len_buf, sizeof (len_buf)) > 1) {
5667c478bd9Sstevel@tonic-gate if (!isdigit(len_buf[0])) {
5677c478bd9Sstevel@tonic-gate (void) printf("invalid length\n");
5687c478bd9Sstevel@tonic-gate continue;
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate buf_len = atoi(len_buf);
5717c478bd9Sstevel@tonic-gate } else
5727c478bd9Sstevel@tonic-gate buf_len = sizeof (gbuf);
5737c478bd9Sstevel@tonic-gate (void) do_getset(fd, cmd, gbuf, buf_len);
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate static void
printe(boolean_t print_errno,char * fmt,...)5787c478bd9Sstevel@tonic-gate printe(boolean_t print_errno, char *fmt, ...)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate va_list ap;
5817c478bd9Sstevel@tonic-gate int error = errno;
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate va_start(ap, fmt);
5847c478bd9Sstevel@tonic-gate (void) printf("*ERROR* ");
5857c478bd9Sstevel@tonic-gate (void) vprintf(fmt, ap);
5867c478bd9Sstevel@tonic-gate va_end(ap);
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate if (print_errno)
5897c478bd9Sstevel@tonic-gate (void) printf(": %s\n", errmsg(error));
5907c478bd9Sstevel@tonic-gate else
5917c478bd9Sstevel@tonic-gate (void) printf("\n");
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate static int
open_device()595a924b63fSVasumathi Sundaram - Sun Microsystems open_device()
5967c478bd9Sstevel@tonic-gate {
5977c478bd9Sstevel@tonic-gate int fd, len;
5986e91bba0SGirish Moodalbail char *mod;
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate for (;;) {
6016e91bba0SGirish Moodalbail len = get_value("module to query ? ", modpath,
6026e91bba0SGirish Moodalbail sizeof (modpath));
6037c478bd9Sstevel@tonic-gate if (len <= 1 ||
6046e91bba0SGirish Moodalbail (len == 2 && (modpath[0] == 'q' || modpath[0] == 'Q')))
6057c478bd9Sstevel@tonic-gate return (-1);
6067c478bd9Sstevel@tonic-gate
6076e91bba0SGirish Moodalbail mod = strrchr(modpath, '/');
6086e91bba0SGirish Moodalbail if (mod != NULL)
6096e91bba0SGirish Moodalbail mod++;
6106e91bba0SGirish Moodalbail else
6116e91bba0SGirish Moodalbail mod = modpath;
6126e91bba0SGirish Moodalbail if (ndd_str2proto(mod) == MOD_PROTO_NONE) {
6136e91bba0SGirish Moodalbail if ((fd = open(modpath, O_RDWR)) == -1) {
6146e91bba0SGirish Moodalbail printe(B_TRUE, "open of %s failed", modpath);
6157c478bd9Sstevel@tonic-gate continue;
6167c478bd9Sstevel@tonic-gate }
6176e91bba0SGirish Moodalbail } else {
6186e91bba0SGirish Moodalbail return (0);
6196e91bba0SGirish Moodalbail }
6207c478bd9Sstevel@tonic-gate
6216e91bba0SGirish Moodalbail gldv3_warning(modpath);
6224045d941Ssowmini
6237c478bd9Sstevel@tonic-gate if (isastream(fd))
6247c478bd9Sstevel@tonic-gate return (fd);
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate (void) close(fd);
6276e91bba0SGirish Moodalbail printe(B_FALSE, "%s is not a streams device", modpath);
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate static void
fatal(char * fmt,...)6327c478bd9Sstevel@tonic-gate fatal(char *fmt, ...)
6337c478bd9Sstevel@tonic-gate {
6347c478bd9Sstevel@tonic-gate va_list ap;
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate va_start(ap, fmt);
6377c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap);
6387c478bd9Sstevel@tonic-gate va_end(ap);
6397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n");
6407c478bd9Sstevel@tonic-gate
6417c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate static char *
errmsg(int error)6457c478bd9Sstevel@tonic-gate errmsg(int error)
6467c478bd9Sstevel@tonic-gate {
6477c478bd9Sstevel@tonic-gate char *msg = strerror(error);
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate return (msg != NULL ? msg : "unknown error");
6507c478bd9Sstevel@tonic-gate }
651