xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/ndd.c (revision 13125:34b1540309cc)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56512Ssowmini  * Common Development and Distribution License (the "License").
66512Ssowmini  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*13125SGirish.Moodalbail@oracle.COM  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
24*13125SGirish.Moodalbail@oracle.COM /* Copyright (c) 1990 Mentat Inc. */
250Sstevel@tonic-gate 
26*13125SGirish.Moodalbail@oracle.COM #include <assert.h>
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <errno.h>
290Sstevel@tonic-gate #include <ctype.h>
300Sstevel@tonic-gate #include <stdarg.h>
310Sstevel@tonic-gate #include <fcntl.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <sys/types.h>
340Sstevel@tonic-gate #include <stropts.h>
3512016SGirish.Moodalbail@Sun.COM #include <inet/tunables.h>
360Sstevel@tonic-gate #include <inet/nd.h>
370Sstevel@tonic-gate #include <string.h>
3812016SGirish.Moodalbail@Sun.COM #include <strings.h>
390Sstevel@tonic-gate #include <stdlib.h>
406512Ssowmini #include <libdllink.h>
416512Ssowmini #include <libintl.h>
4212016SGirish.Moodalbail@Sun.COM #include <libipadm.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static boolean_t do_getset(int fd, int cmd, char *buf, int buf_len);
450Sstevel@tonic-gate static int	get_value(char *msg, char *buf, int buf_len);
460Sstevel@tonic-gate static void	name_print(char *buf);
470Sstevel@tonic-gate static void	getset_interactive(int fd);
488589SVasumathi.Sundaram@Sun.COM static int	open_device(void);
490Sstevel@tonic-gate static char	*errmsg(int err);
500Sstevel@tonic-gate static void	fatal(char *fmt, ...);
510Sstevel@tonic-gate static void	printe(boolean_t print_errno, char *fmt, ...);
520Sstevel@tonic-gate 
5312016SGirish.Moodalbail@Sun.COM static char	modpath[128];	/* path to module */
5412016SGirish.Moodalbail@Sun.COM static char	gbuf[65536];	/* need large buffer to retrieve all names */
550Sstevel@tonic-gate static char	usage_str[] =	"usage: ndd -set device_name name value\n"
560Sstevel@tonic-gate 				"       ndd [-get] device_name name [name ...]";
570Sstevel@tonic-gate 
587776SSowmini.Varadhan@Sun.COM /*
5912016SGirish.Moodalbail@Sun.COM  * Maps old ndd_name to the new ipadm_name. Any ndd property that is moved to
6012016SGirish.Moodalbail@Sun.COM  * libipadm should have an entry here to ensure backward compatibility
6112016SGirish.Moodalbail@Sun.COM  */
6212016SGirish.Moodalbail@Sun.COM typedef struct ndd2ipadm_map {
6312016SGirish.Moodalbail@Sun.COM 	char	*ndd_name;
6412016SGirish.Moodalbail@Sun.COM 	char	*ipadm_name;
6512016SGirish.Moodalbail@Sun.COM 	uint_t	ipadm_proto;
6612016SGirish.Moodalbail@Sun.COM 	uint_t	ipadm_flags;
6712016SGirish.Moodalbail@Sun.COM 	uint_t	ndd_perm;
6812016SGirish.Moodalbail@Sun.COM } ndd2ipadm_map_t;
6912016SGirish.Moodalbail@Sun.COM 
7012016SGirish.Moodalbail@Sun.COM static ndd2ipadm_map_t map[] = {
7112016SGirish.Moodalbail@Sun.COM 	{ "ip_def_ttl",			"ttl",		MOD_PROTO_IPV4, 0, 0 },
7212016SGirish.Moodalbail@Sun.COM 	{ "ip6_def_hops",		"hoplimit",	MOD_PROTO_IPV6, 0, 0 },
7312016SGirish.Moodalbail@Sun.COM 	{ "ip_forwarding",		"forwarding",	MOD_PROTO_IPV4, 0, 0 },
7412016SGirish.Moodalbail@Sun.COM 	{ "ip6_forwarding",		"forwarding",	MOD_PROTO_IPV6, 0, 0 },
7512016SGirish.Moodalbail@Sun.COM 	{ "icmp_recv_hiwat",		"recv_maxbuf",	MOD_PROTO_RAWIP, 0, 0 },
7612016SGirish.Moodalbail@Sun.COM 	{ "icmp_xmit_hiwat",		"send_maxbuf",	MOD_PROTO_RAWIP, 0, 0 },
7712016SGirish.Moodalbail@Sun.COM 	{ "tcp_ecn_permitted",		"ecn",		MOD_PROTO_TCP, 0, 0 },
7812016SGirish.Moodalbail@Sun.COM 	{ "tcp_extra_priv_ports_add",	"extra_priv_ports",	MOD_PROTO_TCP,
7912016SGirish.Moodalbail@Sun.COM 	    IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE },
8012016SGirish.Moodalbail@Sun.COM 	{ "tcp_extra_priv_ports_del",	"extra_priv_ports",	MOD_PROTO_TCP,
8112016SGirish.Moodalbail@Sun.COM 	    IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE },
8212016SGirish.Moodalbail@Sun.COM 	{ "tcp_extra_priv_ports",	"extra_priv_ports",	MOD_PROTO_TCP,
8312016SGirish.Moodalbail@Sun.COM 	    0, MOD_PROP_PERM_READ },
8412016SGirish.Moodalbail@Sun.COM 	{ "tcp_largest_anon_port",	"largest_anon_port",	MOD_PROTO_TCP,
8512016SGirish.Moodalbail@Sun.COM 	    0, 0 },
8612016SGirish.Moodalbail@Sun.COM 	{ "tcp_recv_hiwat",		"recv_maxbuf",	MOD_PROTO_TCP, 0, 0 },
8712016SGirish.Moodalbail@Sun.COM 	{ "tcp_sack_permitted",		"sack",		MOD_PROTO_TCP, 0, 0 },
8812016SGirish.Moodalbail@Sun.COM 	{ "tcp_xmit_hiwat",		"send_maxbuf",	MOD_PROTO_TCP, 0, 0 },
8912016SGirish.Moodalbail@Sun.COM 	{ "tcp_smallest_anon_port",	"smallest_anon_port",	MOD_PROTO_TCP,
9012016SGirish.Moodalbail@Sun.COM 	    0, 0 },
9112016SGirish.Moodalbail@Sun.COM 	{ "tcp_smallest_nonpriv_port",	"smallest_nonpriv_port", MOD_PROTO_TCP,
9212016SGirish.Moodalbail@Sun.COM 	    0, 0 },
9312016SGirish.Moodalbail@Sun.COM 	{ "udp_extra_priv_ports_add",	"extra_priv_ports",	MOD_PROTO_UDP,
9412016SGirish.Moodalbail@Sun.COM 	    IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE },
9512016SGirish.Moodalbail@Sun.COM 	{ "udp_extra_priv_ports_del",	"extra_priv_ports",	MOD_PROTO_UDP,
9612016SGirish.Moodalbail@Sun.COM 	    IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE },
9712016SGirish.Moodalbail@Sun.COM 	{ "udp_extra_priv_ports",	"extra_priv_ports",	MOD_PROTO_UDP,
9812016SGirish.Moodalbail@Sun.COM 	    0, MOD_PROP_PERM_READ },
9912016SGirish.Moodalbail@Sun.COM 	{ "udp_largest_anon_port",	"largest_anon_port",    MOD_PROTO_UDP,
10012016SGirish.Moodalbail@Sun.COM 	    0, 0 },
10112016SGirish.Moodalbail@Sun.COM 	{ "udp_recv_hiwat",		"recv_maxbuf",	MOD_PROTO_UDP, 0, 0 },
10212016SGirish.Moodalbail@Sun.COM 	{ "udp_xmit_hiwat",		"send_maxbuf",	MOD_PROTO_UDP, 0, 0 },
10312016SGirish.Moodalbail@Sun.COM 	{ "udp_smallest_anon_port",	"smallest_anon_port",	MOD_PROTO_UDP,
10412016SGirish.Moodalbail@Sun.COM 	    0, 0 },
10512016SGirish.Moodalbail@Sun.COM 	{ "udp_smallest_nonpriv_port",	"smallest_nonpriv_port", MOD_PROTO_UDP,
10612016SGirish.Moodalbail@Sun.COM 	    0, 0 },
10712016SGirish.Moodalbail@Sun.COM 	{ "sctp_extra_priv_ports_add",	"extra_priv_ports",	MOD_PROTO_SCTP,
10812016SGirish.Moodalbail@Sun.COM 	    IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE },
10912016SGirish.Moodalbail@Sun.COM 	{ "sctp_extra_priv_ports_del",	"extra_priv_ports",	MOD_PROTO_SCTP,
11012016SGirish.Moodalbail@Sun.COM 	    IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE },
11112016SGirish.Moodalbail@Sun.COM 	{ "sctp_extra_priv_ports",	"extra_priv_ports",	MOD_PROTO_SCTP,
11212016SGirish.Moodalbail@Sun.COM 	    0, MOD_PROP_PERM_READ },
11312016SGirish.Moodalbail@Sun.COM 	{ "sctp_largest_anon_port",	"largest_anon_port",	MOD_PROTO_SCTP,
11412016SGirish.Moodalbail@Sun.COM 	    0, 0 },
11512016SGirish.Moodalbail@Sun.COM 	{ "sctp_recv_hiwat",		"recv_maxbuf",	MOD_PROTO_SCTP, 0, 0 },
11612016SGirish.Moodalbail@Sun.COM 	{ "sctp_xmit_hiwat",		"send_maxbuf",	MOD_PROTO_SCTP, 0, 0 },
11712016SGirish.Moodalbail@Sun.COM 	{ "sctp_smallest_anon_port",	"smallest_anon_port",	MOD_PROTO_SCTP,
11812016SGirish.Moodalbail@Sun.COM 	    0, 0 },
11912016SGirish.Moodalbail@Sun.COM 	{ "sctp_smallest_nonpriv_port",	"smallest_nonpriv_port", MOD_PROTO_SCTP,
12012016SGirish.Moodalbail@Sun.COM 	    0, 0 },
12112016SGirish.Moodalbail@Sun.COM 	{ NULL, NULL, 0, 0, 0 }
12212016SGirish.Moodalbail@Sun.COM };
12312016SGirish.Moodalbail@Sun.COM 
12412016SGirish.Moodalbail@Sun.COM static uint_t
ndd_str2proto(const char * protostr)12512016SGirish.Moodalbail@Sun.COM ndd_str2proto(const char *protostr)
12612016SGirish.Moodalbail@Sun.COM {
12712016SGirish.Moodalbail@Sun.COM 	if (strcmp(protostr, "tcp") == 0 ||
12812016SGirish.Moodalbail@Sun.COM 	    strcmp(protostr, "tcp6") == 0) {
12912016SGirish.Moodalbail@Sun.COM 		return (MOD_PROTO_TCP);
13012016SGirish.Moodalbail@Sun.COM 	} else if (strcmp(protostr, "udp") == 0 ||
13112016SGirish.Moodalbail@Sun.COM 	    strcmp(protostr, "udp6") == 0) {
13212016SGirish.Moodalbail@Sun.COM 		return (MOD_PROTO_UDP);
13312016SGirish.Moodalbail@Sun.COM 	} else if (strcmp(protostr, "ip") == 0 ||
13412016SGirish.Moodalbail@Sun.COM 	    strcmp(protostr, "ip6") == 0 ||
13512016SGirish.Moodalbail@Sun.COM 	    strcmp(protostr, "arp") == 0) {
13612016SGirish.Moodalbail@Sun.COM 		return (MOD_PROTO_IP);
13712016SGirish.Moodalbail@Sun.COM 	} else if (strcmp(protostr, "icmp") == 0 ||
13812016SGirish.Moodalbail@Sun.COM 	    strcmp(protostr, "icmp6") == 0) {
13912016SGirish.Moodalbail@Sun.COM 		return (MOD_PROTO_RAWIP);
14012016SGirish.Moodalbail@Sun.COM 	} else if (strcmp(protostr, "sctp") == 0 ||
14112016SGirish.Moodalbail@Sun.COM 	    strcmp(protostr, "sctp6") == 0) {
14212016SGirish.Moodalbail@Sun.COM 		return (MOD_PROTO_SCTP);
14312016SGirish.Moodalbail@Sun.COM 	}
14412016SGirish.Moodalbail@Sun.COM 	return (MOD_PROTO_NONE);
14512016SGirish.Moodalbail@Sun.COM }
14612016SGirish.Moodalbail@Sun.COM 
14712016SGirish.Moodalbail@Sun.COM static char *
ndd_perm2str(uint_t perm)14812016SGirish.Moodalbail@Sun.COM ndd_perm2str(uint_t perm)
14912016SGirish.Moodalbail@Sun.COM {
15012016SGirish.Moodalbail@Sun.COM 	switch (perm) {
15112016SGirish.Moodalbail@Sun.COM 	case MOD_PROP_PERM_READ:
15212016SGirish.Moodalbail@Sun.COM 		return ("read only");
15312016SGirish.Moodalbail@Sun.COM 	case MOD_PROP_PERM_WRITE:
15412016SGirish.Moodalbail@Sun.COM 		return ("write only");
15512016SGirish.Moodalbail@Sun.COM 	case MOD_PROP_PERM_RW:
15612016SGirish.Moodalbail@Sun.COM 		return ("read and write");
15712016SGirish.Moodalbail@Sun.COM 	}
15812016SGirish.Moodalbail@Sun.COM 
15912016SGirish.Moodalbail@Sun.COM 	return (NULL);
16012016SGirish.Moodalbail@Sun.COM }
16112016SGirish.Moodalbail@Sun.COM 
16212016SGirish.Moodalbail@Sun.COM /*
163*13125SGirish.Moodalbail@oracle.COM  * Print all the protocol properties for the given protocol name. The kernel
164*13125SGirish.Moodalbail@oracle.COM  * returns all the properties for the given protocol therefore we have to
165*13125SGirish.Moodalbail@oracle.COM  * apply some filters before we print them.
166*13125SGirish.Moodalbail@oracle.COM  *
167*13125SGirish.Moodalbail@oracle.COM  *	- convert any new ipadm name to old ndd name using the table.
168*13125SGirish.Moodalbail@oracle.COM  *	  For example: `sack' --> `tcp_sack_permitted'.
169*13125SGirish.Moodalbail@oracle.COM  *
170*13125SGirish.Moodalbail@oracle.COM  *	- replace leading underscores with protocol name.
171*13125SGirish.Moodalbail@oracle.COM  *	  For example: `_strong_iss' --> `tcp_strong_iss'
172*13125SGirish.Moodalbail@oracle.COM  *
173*13125SGirish.Moodalbail@oracle.COM  *	- don't print new public properties that are supported only by ipadm(1M)
174*13125SGirish.Moodalbail@oracle.COM  *	  For example: `hostmodel' should be supported only from ipadm(1M).
175*13125SGirish.Moodalbail@oracle.COM  *	  Such properties are identified by not having leading '_' and not
176*13125SGirish.Moodalbail@oracle.COM  *	  being present in the mapping table.
17712016SGirish.Moodalbail@Sun.COM  */
17812016SGirish.Moodalbail@Sun.COM static void
print_ipadm2ndd(char * oldbuf,uint_t obufsize)17912016SGirish.Moodalbail@Sun.COM print_ipadm2ndd(char *oldbuf, uint_t obufsize)
18012016SGirish.Moodalbail@Sun.COM {
18112016SGirish.Moodalbail@Sun.COM 	ndd2ipadm_map_t	*nimap;
18212016SGirish.Moodalbail@Sun.COM 	char		*pname, *rwtag, *protostr;
18312016SGirish.Moodalbail@Sun.COM 	uint_t		proto, perm;
18412016SGirish.Moodalbail@Sun.COM 	boolean_t	matched;
18512016SGirish.Moodalbail@Sun.COM 
18612016SGirish.Moodalbail@Sun.COM 	pname = oldbuf;
18712016SGirish.Moodalbail@Sun.COM 	while (pname[0] && pname < (oldbuf + obufsize - 1)) {
18812016SGirish.Moodalbail@Sun.COM 		for (protostr = pname; !isspace(*protostr); protostr++)
18912016SGirish.Moodalbail@Sun.COM 			;
19012016SGirish.Moodalbail@Sun.COM 		*protostr++ = '\0';
19112016SGirish.Moodalbail@Sun.COM 		/* protostr now points to protocol */
19212016SGirish.Moodalbail@Sun.COM 
19312016SGirish.Moodalbail@Sun.COM 		for (rwtag = protostr; !isspace(*rwtag); rwtag++)
19412016SGirish.Moodalbail@Sun.COM 			;
19512016SGirish.Moodalbail@Sun.COM 		*rwtag++ = '\0';
19612016SGirish.Moodalbail@Sun.COM 		/* rwtag now points to permissions */
19712016SGirish.Moodalbail@Sun.COM 
19812016SGirish.Moodalbail@Sun.COM 		proto = atoi(protostr);
19912016SGirish.Moodalbail@Sun.COM 		perm = atoi(rwtag);
20012016SGirish.Moodalbail@Sun.COM 		matched = B_FALSE;
20112016SGirish.Moodalbail@Sun.COM 		for (nimap = map; nimap->ndd_name != NULL; nimap++) {
20212016SGirish.Moodalbail@Sun.COM 			if (strcmp(pname, nimap->ipadm_name) != 0 ||
20312016SGirish.Moodalbail@Sun.COM 			    !(nimap->ipadm_proto & proto))
20412016SGirish.Moodalbail@Sun.COM 				continue;
20512016SGirish.Moodalbail@Sun.COM 
20612016SGirish.Moodalbail@Sun.COM 			matched = B_TRUE;
20712016SGirish.Moodalbail@Sun.COM 			if (nimap->ndd_perm != 0)
20812016SGirish.Moodalbail@Sun.COM 				perm = nimap->ndd_perm;
20912016SGirish.Moodalbail@Sun.COM 			(void) printf("%-30s (%s)\n", nimap->ndd_name,
21012016SGirish.Moodalbail@Sun.COM 			    ndd_perm2str(perm));
21112016SGirish.Moodalbail@Sun.COM 		}
212*13125SGirish.Moodalbail@oracle.COM 		/*
213*13125SGirish.Moodalbail@oracle.COM 		 * print only if it's a private property. We should
214*13125SGirish.Moodalbail@oracle.COM 		 * not be printing any new public property in ndd(1M)
215*13125SGirish.Moodalbail@oracle.COM 		 * output.
216*13125SGirish.Moodalbail@oracle.COM 		 */
217*13125SGirish.Moodalbail@oracle.COM 		if (!matched && pname[0] == '_') {
218*13125SGirish.Moodalbail@oracle.COM 			char	tmpstr[512];
219*13125SGirish.Moodalbail@oracle.COM 			int	err;
220*13125SGirish.Moodalbail@oracle.COM 
221*13125SGirish.Moodalbail@oracle.COM 			err = ipadm_new2legacy_propname(pname, tmpstr,
222*13125SGirish.Moodalbail@oracle.COM 			    sizeof (tmpstr), proto);
223*13125SGirish.Moodalbail@oracle.COM 			assert(err != -1);
224*13125SGirish.Moodalbail@oracle.COM 
225*13125SGirish.Moodalbail@oracle.COM 			(void) printf("%-30s (%s)\n", tmpstr,
22612016SGirish.Moodalbail@Sun.COM 			    ndd_perm2str(perm));
227*13125SGirish.Moodalbail@oracle.COM 		}
22812016SGirish.Moodalbail@Sun.COM 		for (pname = rwtag; *pname++; )
22912016SGirish.Moodalbail@Sun.COM 			;
23012016SGirish.Moodalbail@Sun.COM 	}
23112016SGirish.Moodalbail@Sun.COM }
23212016SGirish.Moodalbail@Sun.COM 
23312016SGirish.Moodalbail@Sun.COM /*
23412016SGirish.Moodalbail@Sun.COM  * get/set the value for a given property by calling into libipadm. The
23512016SGirish.Moodalbail@Sun.COM  * IPH_LEGACY flag is used by libipadm for special handling. For some
23612016SGirish.Moodalbail@Sun.COM  * properties, libipadm.so displays strings (for e.g., on/off,
23712016SGirish.Moodalbail@Sun.COM  * never/passive/active, et al) instead of numerals. However ndd(1M) always
23812016SGirish.Moodalbail@Sun.COM  * printed numberals. This flag will help in avoiding printing strings.
23912016SGirish.Moodalbail@Sun.COM  */
24012016SGirish.Moodalbail@Sun.COM static boolean_t
do_ipadm_getset(int cmd,char * buf,int buflen)24112016SGirish.Moodalbail@Sun.COM do_ipadm_getset(int cmd, char *buf, int buflen)
24212016SGirish.Moodalbail@Sun.COM {
24312016SGirish.Moodalbail@Sun.COM 	ndd2ipadm_map_t	*nimap;
24412016SGirish.Moodalbail@Sun.COM 	ipadm_handle_t	iph = NULL;
24512016SGirish.Moodalbail@Sun.COM 	ipadm_status_t	status;
24612016SGirish.Moodalbail@Sun.COM 	char		*mod;
24712016SGirish.Moodalbail@Sun.COM 	uint_t		proto, perm = 0, flags = 0;
248*13125SGirish.Moodalbail@oracle.COM 	char		*pname, *pvalp, nname[512];
24912016SGirish.Moodalbail@Sun.COM 	int		i;
25012016SGirish.Moodalbail@Sun.COM 
25112016SGirish.Moodalbail@Sun.COM 	if ((mod = strrchr(modpath, '/')) == NULL)
25212016SGirish.Moodalbail@Sun.COM 		mod = modpath;
25312016SGirish.Moodalbail@Sun.COM 	else
25412016SGirish.Moodalbail@Sun.COM 		++mod;
25512016SGirish.Moodalbail@Sun.COM 	if ((proto = ndd_str2proto(mod)) == MOD_PROTO_NONE)
25612016SGirish.Moodalbail@Sun.COM 		return (B_FALSE);
25712016SGirish.Moodalbail@Sun.COM 
25812016SGirish.Moodalbail@Sun.COM 	if ((status = ipadm_open(&iph, IPH_LEGACY)) != IPADM_SUCCESS)
25912016SGirish.Moodalbail@Sun.COM 		goto fail;
26012016SGirish.Moodalbail@Sun.COM 
26112016SGirish.Moodalbail@Sun.COM 	pname = buf;
26212016SGirish.Moodalbail@Sun.COM 	for (nimap = map; nimap->ndd_name != NULL; nimap++) {
263*13125SGirish.Moodalbail@oracle.COM 		if (strcmp(pname, nimap->ndd_name) == 0) {
264*13125SGirish.Moodalbail@oracle.COM 			pname = nimap->ipadm_name;
265*13125SGirish.Moodalbail@oracle.COM 			proto = nimap->ipadm_proto;
266*13125SGirish.Moodalbail@oracle.COM 			flags = nimap->ipadm_flags;
267*13125SGirish.Moodalbail@oracle.COM 			perm = nimap->ndd_perm;
26812016SGirish.Moodalbail@Sun.COM 			break;
269*13125SGirish.Moodalbail@oracle.COM 		}
27012016SGirish.Moodalbail@Sun.COM 	}
271*13125SGirish.Moodalbail@oracle.COM 
272*13125SGirish.Moodalbail@oracle.COM 	if (nimap->ndd_name == NULL && strcmp(pname, "?") != 0) {
273*13125SGirish.Moodalbail@oracle.COM 		/* do not allow set/get of public properties from ndd(1M) */
274*13125SGirish.Moodalbail@oracle.COM 		if (ipadm_legacy2new_propname(pname, nname, sizeof (nname),
275*13125SGirish.Moodalbail@oracle.COM 		    &proto) != 0) {
276*13125SGirish.Moodalbail@oracle.COM 			status = IPADM_PROP_UNKNOWN;
277*13125SGirish.Moodalbail@oracle.COM 			goto fail;
278*13125SGirish.Moodalbail@oracle.COM 		} else {
279*13125SGirish.Moodalbail@oracle.COM 			pname = nname;
280*13125SGirish.Moodalbail@oracle.COM 		}
28112016SGirish.Moodalbail@Sun.COM 	}
282*13125SGirish.Moodalbail@oracle.COM 
28312016SGirish.Moodalbail@Sun.COM 	if (cmd == ND_GET) {
28412016SGirish.Moodalbail@Sun.COM 		char		propval[MAXPROPVALLEN], allprop[64536];
28512016SGirish.Moodalbail@Sun.COM 		uint_t		pvalsz;
28612016SGirish.Moodalbail@Sun.COM 		sa_family_t	af = AF_UNSPEC;
28712016SGirish.Moodalbail@Sun.COM 		int		err;
28812016SGirish.Moodalbail@Sun.COM 
28912016SGirish.Moodalbail@Sun.COM 		if (perm == MOD_PROP_PERM_WRITE)
29012016SGirish.Moodalbail@Sun.COM 			fatal("operation failed: Permission denied");
29112016SGirish.Moodalbail@Sun.COM 
29212016SGirish.Moodalbail@Sun.COM 		if (strcmp(pname, "?") == 0) {
29312016SGirish.Moodalbail@Sun.COM 			pvalp = allprop;
29412016SGirish.Moodalbail@Sun.COM 			pvalsz = sizeof (allprop);
29512016SGirish.Moodalbail@Sun.COM 		} else {
29612016SGirish.Moodalbail@Sun.COM 			pvalp = propval;
29712016SGirish.Moodalbail@Sun.COM 			pvalsz = sizeof (propval);
29812016SGirish.Moodalbail@Sun.COM 		}
29912016SGirish.Moodalbail@Sun.COM 
30012016SGirish.Moodalbail@Sun.COM 		status = ipadm_get_prop(iph, pname, pvalp, &pvalsz, proto,
30112016SGirish.Moodalbail@Sun.COM 		    IPADM_OPT_ACTIVE);
30212016SGirish.Moodalbail@Sun.COM 		if (status != IPADM_SUCCESS)
30312016SGirish.Moodalbail@Sun.COM 			goto fail;
30412016SGirish.Moodalbail@Sun.COM 
30512016SGirish.Moodalbail@Sun.COM 		if (strcmp(pname, "?") == 0) {
30612016SGirish.Moodalbail@Sun.COM 			(void) print_ipadm2ndd(pvalp, pvalsz);
30712016SGirish.Moodalbail@Sun.COM 		} else {
30812016SGirish.Moodalbail@Sun.COM 			char *tmp = pvalp;
30912016SGirish.Moodalbail@Sun.COM 
31012016SGirish.Moodalbail@Sun.COM 			/*
31112016SGirish.Moodalbail@Sun.COM 			 * For backward compatibility if there are multiple
31212016SGirish.Moodalbail@Sun.COM 			 * values print each value in it's own line.
31312016SGirish.Moodalbail@Sun.COM 			 */
31412016SGirish.Moodalbail@Sun.COM 			while (*tmp != '\0') {
31512016SGirish.Moodalbail@Sun.COM 				if (*tmp == ',')
31612016SGirish.Moodalbail@Sun.COM 					*tmp = '\n';
31712016SGirish.Moodalbail@Sun.COM 				tmp++;
31812016SGirish.Moodalbail@Sun.COM 			}
31912016SGirish.Moodalbail@Sun.COM 			(void) printf("%s\n", pvalp);
32012016SGirish.Moodalbail@Sun.COM 		}
32112016SGirish.Moodalbail@Sun.COM 		(void) fflush(stdout);
32212016SGirish.Moodalbail@Sun.COM 	} else {
32312016SGirish.Moodalbail@Sun.COM 		if (perm == MOD_PROP_PERM_READ)
32412016SGirish.Moodalbail@Sun.COM 			fatal("operation failed: Permission denied");
32512016SGirish.Moodalbail@Sun.COM 
32612016SGirish.Moodalbail@Sun.COM 		/* walk past the property name to find the property value */
32712016SGirish.Moodalbail@Sun.COM 		for (i = 0; buf[i] != '\0'; i++)
32812016SGirish.Moodalbail@Sun.COM 			;
32912016SGirish.Moodalbail@Sun.COM 
33012016SGirish.Moodalbail@Sun.COM 		pvalp = &buf[++i];
33112016SGirish.Moodalbail@Sun.COM 		status = ipadm_set_prop(iph, pname, pvalp, proto,
33212016SGirish.Moodalbail@Sun.COM 		    flags|IPADM_OPT_ACTIVE);
33312016SGirish.Moodalbail@Sun.COM 	}
33412016SGirish.Moodalbail@Sun.COM fail:
33512016SGirish.Moodalbail@Sun.COM 	ipadm_close(iph);
33612016SGirish.Moodalbail@Sun.COM 	if (status != IPADM_SUCCESS)
33712016SGirish.Moodalbail@Sun.COM 		fatal("operation failed: %s", ipadm_status2str(status));
33812016SGirish.Moodalbail@Sun.COM 	return (B_TRUE);
33912016SGirish.Moodalbail@Sun.COM }
34012016SGirish.Moodalbail@Sun.COM 
34112016SGirish.Moodalbail@Sun.COM /*
3427776SSowmini.Varadhan@Sun.COM  * gldv3_warning() catches the case of /sbin/ndd abuse to administer
3437776SSowmini.Varadhan@Sun.COM  * ethernet/MII props. Note that /sbin/ndd has not been abused
3447776SSowmini.Varadhan@Sun.COM  * for administration of other datalink types, which makes it permissible
3457776SSowmini.Varadhan@Sun.COM  * to test for support of the flowctrl property.
3467776SSowmini.Varadhan@Sun.COM  */
3476512Ssowmini static void
gldv3_warning(char * module)3488589SVasumathi.Sundaram@Sun.COM gldv3_warning(char *module)
3496512Ssowmini {
3506512Ssowmini 	datalink_id_t	linkid;
3516512Ssowmini 	dladm_status_t	status;
3526512Ssowmini 	char		buf[DLADM_PROP_VAL_MAX], *cp;
3537776SSowmini.Varadhan@Sun.COM 	uint_t		cnt = 1;
3546512Ssowmini 	char		*link;
3558589SVasumathi.Sundaram@Sun.COM 	dladm_handle_t	handle;
3566512Ssowmini 
3576512Ssowmini 	link = strrchr(module, '/');
3586512Ssowmini 	if (link == NULL)
3596512Ssowmini 		return;
3608589SVasumathi.Sundaram@Sun.COM 
3618589SVasumathi.Sundaram@Sun.COM 	if (dladm_open(&handle) != DLADM_STATUS_OK)
3626512Ssowmini 		return;
3638589SVasumathi.Sundaram@Sun.COM 
3648589SVasumathi.Sundaram@Sun.COM 	status = dladm_name2info(handle, ++link, &linkid, NULL, NULL, NULL);
3658589SVasumathi.Sundaram@Sun.COM 	if (status == DLADM_STATUS_OK) {
3668589SVasumathi.Sundaram@Sun.COM 		cp = buf;
3678589SVasumathi.Sundaram@Sun.COM 		status = dladm_get_linkprop(handle, linkid,
3688589SVasumathi.Sundaram@Sun.COM 		    DLADM_PROP_VAL_CURRENT, "flowctrl", &cp, &cnt);
3698589SVasumathi.Sundaram@Sun.COM 		if (status == DLADM_STATUS_OK) {
3708589SVasumathi.Sundaram@Sun.COM 			(void) fprintf(stderr, gettext(
3718589SVasumathi.Sundaram@Sun.COM 			    "WARNING: The ndd commands for datalink "
3728589SVasumathi.Sundaram@Sun.COM 			    "administration are obsolete and may be "
3738589SVasumathi.Sundaram@Sun.COM 			    "removed in a future release of Solaris. "
3748589SVasumathi.Sundaram@Sun.COM 			    "Use dladm(1M) to manage datalink tunables.\n"));
3758589SVasumathi.Sundaram@Sun.COM 		}
3768589SVasumathi.Sundaram@Sun.COM 	}
3778589SVasumathi.Sundaram@Sun.COM 	dladm_close(handle);
3786512Ssowmini }
3796512Ssowmini 
3800Sstevel@tonic-gate /* ARGSUSED */
3810Sstevel@tonic-gate int
main(int argc,char ** argv)3820Sstevel@tonic-gate main(int argc, char **argv)
3830Sstevel@tonic-gate {
38412016SGirish.Moodalbail@Sun.COM 	char	*cp, *value, *mod;
3850Sstevel@tonic-gate 	int	cmd;
38612016SGirish.Moodalbail@Sun.COM 	int	fd = 0;
3876512Ssowmini 
3880Sstevel@tonic-gate 	if (!(cp = *++argv)) {
3898589SVasumathi.Sundaram@Sun.COM 		while ((fd = open_device()) != -1) {
3900Sstevel@tonic-gate 			getset_interactive(fd);
3910Sstevel@tonic-gate 			(void) close(fd);
3920Sstevel@tonic-gate 		}
3930Sstevel@tonic-gate 		return (EXIT_SUCCESS);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	cmd = ND_GET;
3970Sstevel@tonic-gate 	if (cp[0] == '-') {
3980Sstevel@tonic-gate 		if (strncmp(&cp[1], "set", 3) == 0)
3990Sstevel@tonic-gate 			cmd = ND_SET;
4000Sstevel@tonic-gate 		else if (strncmp(&cp[1], "get", 3) != 0)
4010Sstevel@tonic-gate 			fatal(usage_str);
4020Sstevel@tonic-gate 		if (!(cp = *++argv))
4030Sstevel@tonic-gate 			fatal(usage_str);
4040Sstevel@tonic-gate 	}
40512016SGirish.Moodalbail@Sun.COM 
4068589SVasumathi.Sundaram@Sun.COM 	gldv3_warning(cp);
4078453SAnurag.Maskey@Sun.COM 
40812016SGirish.Moodalbail@Sun.COM 	mod = strrchr(cp, '/');
40912016SGirish.Moodalbail@Sun.COM 	if (mod != NULL)
41012016SGirish.Moodalbail@Sun.COM 		mod++;
41112016SGirish.Moodalbail@Sun.COM 	else
41212016SGirish.Moodalbail@Sun.COM 		mod = cp;
4130Sstevel@tonic-gate 
41412016SGirish.Moodalbail@Sun.COM 	if (ndd_str2proto(mod) == MOD_PROTO_NONE) {
41512016SGirish.Moodalbail@Sun.COM 		if ((fd = open(cp, O_RDWR)) == -1)
41612016SGirish.Moodalbail@Sun.COM 			fatal("open of %s failed: %s", cp, errmsg(errno));
41712016SGirish.Moodalbail@Sun.COM 		if (!isastream(fd))
41812016SGirish.Moodalbail@Sun.COM 			fatal("%s is not a streams device", cp);
41912016SGirish.Moodalbail@Sun.COM 	}
4200Sstevel@tonic-gate 
42112016SGirish.Moodalbail@Sun.COM 	(void) strlcpy(modpath, cp, sizeof (modpath));
4220Sstevel@tonic-gate 	if (!(cp = *++argv)) {
4230Sstevel@tonic-gate 		getset_interactive(fd);
4240Sstevel@tonic-gate 		(void) close(fd);
4250Sstevel@tonic-gate 		return (EXIT_SUCCESS);
4260Sstevel@tonic-gate 	}
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	if (cmd == ND_SET) {
4290Sstevel@tonic-gate 		if (!(value = *++argv))
4300Sstevel@tonic-gate 			fatal(usage_str);
4310Sstevel@tonic-gate 		(void) snprintf(gbuf, sizeof (gbuf), "%s%c%s%c", cp, '\0',
4320Sstevel@tonic-gate 		    value, '\0');
4330Sstevel@tonic-gate 		if (!do_getset(fd, cmd, gbuf, sizeof (gbuf)))
4340Sstevel@tonic-gate 			return (EXIT_FAILURE);
4350Sstevel@tonic-gate 	} else {
4360Sstevel@tonic-gate 		do {
4370Sstevel@tonic-gate 			(void) memset(gbuf, '\0', sizeof (gbuf));
4380Sstevel@tonic-gate 			(void) strlcpy(gbuf, cp, sizeof (gbuf));
4390Sstevel@tonic-gate 			if (!do_getset(fd, cmd, gbuf, sizeof (gbuf)))
4400Sstevel@tonic-gate 				return (EXIT_FAILURE);
4410Sstevel@tonic-gate 			if (cp = *++argv)
4420Sstevel@tonic-gate 				(void) putchar('\n');
4430Sstevel@tonic-gate 		} while (cp);
4440Sstevel@tonic-gate 	}
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	(void) close(fd);
4470Sstevel@tonic-gate 	return (EXIT_SUCCESS);
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate static void
name_print(char * buf)4510Sstevel@tonic-gate name_print(char *buf)
4520Sstevel@tonic-gate {
4530Sstevel@tonic-gate 	char *cp, *rwtag;
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	for (cp = buf; cp[0]; ) {
4560Sstevel@tonic-gate 		for (rwtag = cp; !isspace(*rwtag); rwtag++)
4570Sstevel@tonic-gate 			;
4580Sstevel@tonic-gate 		*rwtag++ = '\0';
4590Sstevel@tonic-gate 		while (isspace(*rwtag))
4600Sstevel@tonic-gate 			rwtag++;
4610Sstevel@tonic-gate 		(void) printf("%-30s%s\n", cp, rwtag);
4620Sstevel@tonic-gate 		for (cp = rwtag; *cp++; )
4630Sstevel@tonic-gate 			;
4640Sstevel@tonic-gate 	}
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate /*
4680Sstevel@tonic-gate  * This function is vile, but it's better here than in the kernel.
4690Sstevel@tonic-gate  */
4700Sstevel@tonic-gate static boolean_t
is_obsolete(const char * param)4710Sstevel@tonic-gate is_obsolete(const char *param)
4720Sstevel@tonic-gate {
4730Sstevel@tonic-gate 	if (strcmp(param, "ip_enable_group_ifs") == 0 ||
4740Sstevel@tonic-gate 	    strcmp(param, "ifgrp_status") == 0) {
4750Sstevel@tonic-gate 		(void) fprintf(stderr, "The \"%s\" tunable has been superseded "
4760Sstevel@tonic-gate 		    "by IP Multipathing.\nPlease see the IP Network "
4770Sstevel@tonic-gate 		    "Multipathing Administration Guide for details.\n", param);
4780Sstevel@tonic-gate 		return (B_TRUE);
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 	return (B_FALSE);
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate static boolean_t
do_getset(int fd,int cmd,char * buf,int buf_len)4840Sstevel@tonic-gate do_getset(int fd, int cmd, char *buf, int buf_len)
4850Sstevel@tonic-gate {
4860Sstevel@tonic-gate 	char	*cp;
4870Sstevel@tonic-gate 	struct strioctl	stri;
4880Sstevel@tonic-gate 	boolean_t	is_name_get;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	if (is_obsolete(buf))
4910Sstevel@tonic-gate 		return (B_TRUE);
4920Sstevel@tonic-gate 
49312016SGirish.Moodalbail@Sun.COM 	/*
49412016SGirish.Moodalbail@Sun.COM 	 * See if libipadm can handle this request, i.e., properties on
49512016SGirish.Moodalbail@Sun.COM 	 * following modules arp, ip, ipv4, ipv6, tcp, udp and sctp
49612016SGirish.Moodalbail@Sun.COM 	 */
49712016SGirish.Moodalbail@Sun.COM 	if (do_ipadm_getset(cmd, buf, buf_len))
49812016SGirish.Moodalbail@Sun.COM 		return (B_TRUE);
49912016SGirish.Moodalbail@Sun.COM 
5000Sstevel@tonic-gate 	stri.ic_cmd = cmd;
5010Sstevel@tonic-gate 	stri.ic_timout = 0;
5020Sstevel@tonic-gate 	stri.ic_len = buf_len;
5030Sstevel@tonic-gate 	stri.ic_dp = buf;
5040Sstevel@tonic-gate 	is_name_get = stri.ic_cmd == ND_GET && buf[0] == '?' && buf[1] == '\0';
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	if (ioctl(fd, I_STR, &stri) == -1) {
5070Sstevel@tonic-gate 		if (errno == ENOENT)
5080Sstevel@tonic-gate 			(void) printf("name is non-existent for this module\n"
5090Sstevel@tonic-gate 			    "for a list of valid names, use name '?'\n");
5100Sstevel@tonic-gate 		else
5110Sstevel@tonic-gate 			(void) printf("operation failed: %s\n", errmsg(errno));
5120Sstevel@tonic-gate 		return (B_FALSE);
5130Sstevel@tonic-gate 	}
5140Sstevel@tonic-gate 	if (is_name_get)
5150Sstevel@tonic-gate 		name_print(buf);
5160Sstevel@tonic-gate 	else if (stri.ic_cmd == ND_GET) {
5170Sstevel@tonic-gate 		for (cp = buf; *cp != '\0'; cp += strlen(cp) + 1)
5180Sstevel@tonic-gate 			(void) puts(cp);
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 	(void) fflush(stdout);
5210Sstevel@tonic-gate 	return (B_TRUE);
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate static int
get_value(char * msg,char * buf,int buf_len)5250Sstevel@tonic-gate get_value(char *msg, char *buf, int buf_len)
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate 	int	len;
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	(void) printf("%s", msg);
5300Sstevel@tonic-gate 	(void) fflush(stdout);
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	buf[buf_len-1] = '\0';
5330Sstevel@tonic-gate 	if (fgets(buf, buf_len-1, stdin) == NULL)
5340Sstevel@tonic-gate 		exit(EXIT_SUCCESS);
5350Sstevel@tonic-gate 	len = strlen(buf);
5360Sstevel@tonic-gate 	if (buf[len-1] == '\n')
5370Sstevel@tonic-gate 		buf[len - 1] = '\0';
5380Sstevel@tonic-gate 	else
5390Sstevel@tonic-gate 		len++;
5400Sstevel@tonic-gate 	return (len);
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate static void
getset_interactive(int fd)5440Sstevel@tonic-gate getset_interactive(int fd)
5450Sstevel@tonic-gate {
5460Sstevel@tonic-gate 	int	cmd;
5470Sstevel@tonic-gate 	char	*cp;
5480Sstevel@tonic-gate 	int	len, buf_len;
5490Sstevel@tonic-gate 	char	len_buf[10];
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	for (;;) {
5520Sstevel@tonic-gate 		(void) memset(gbuf, '\0', sizeof (gbuf));
5530Sstevel@tonic-gate 		len = get_value("name to get/set ? ", gbuf, sizeof (gbuf));
5540Sstevel@tonic-gate 		if (len == 1 || (gbuf[0] == 'q' && gbuf[1] == '\0'))
5550Sstevel@tonic-gate 			return;
5560Sstevel@tonic-gate 		for (cp = gbuf; cp < &gbuf[len]; cp++) {
5570Sstevel@tonic-gate 			if (isspace(*cp))
5580Sstevel@tonic-gate 				*cp = '\0';
5590Sstevel@tonic-gate 		}
5600Sstevel@tonic-gate 		cmd = ND_GET;
5610Sstevel@tonic-gate 		if (gbuf[0] != '?' &&
5620Sstevel@tonic-gate 		    get_value("value ? ", &gbuf[len], sizeof (gbuf) - len) > 1)
5630Sstevel@tonic-gate 			cmd = ND_SET;
5640Sstevel@tonic-gate 		if (cmd == ND_GET && gbuf[0] != '?' &&
5650Sstevel@tonic-gate 		    get_value("length ? ", len_buf, sizeof (len_buf)) > 1) {
5660Sstevel@tonic-gate 			if (!isdigit(len_buf[0])) {
5670Sstevel@tonic-gate 				(void) printf("invalid length\n");
5680Sstevel@tonic-gate 				continue;
5690Sstevel@tonic-gate 			}
5700Sstevel@tonic-gate 			buf_len = atoi(len_buf);
5710Sstevel@tonic-gate 		} else
5720Sstevel@tonic-gate 			buf_len = sizeof (gbuf);
5730Sstevel@tonic-gate 		(void) do_getset(fd, cmd, gbuf, buf_len);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate static void
printe(boolean_t print_errno,char * fmt,...)5780Sstevel@tonic-gate printe(boolean_t print_errno, char *fmt, ...)
5790Sstevel@tonic-gate {
5800Sstevel@tonic-gate 	va_list	ap;
5810Sstevel@tonic-gate 	int error = errno;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	va_start(ap, fmt);
5840Sstevel@tonic-gate 	(void) printf("*ERROR* ");
5850Sstevel@tonic-gate 	(void) vprintf(fmt, ap);
5860Sstevel@tonic-gate 	va_end(ap);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	if (print_errno)
5890Sstevel@tonic-gate 		(void) printf(": %s\n", errmsg(error));
5900Sstevel@tonic-gate 	else
5910Sstevel@tonic-gate 		(void) printf("\n");
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate static int
open_device()5958589SVasumathi.Sundaram@Sun.COM open_device()
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate 	int	fd, len;
59812016SGirish.Moodalbail@Sun.COM 	char	*mod;
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	for (;;) {
60112016SGirish.Moodalbail@Sun.COM 		len = get_value("module to query ? ", modpath,
60212016SGirish.Moodalbail@Sun.COM 		    sizeof (modpath));
6030Sstevel@tonic-gate 		if (len <= 1 ||
60412016SGirish.Moodalbail@Sun.COM 		    (len == 2 && (modpath[0] == 'q' || modpath[0] == 'Q')))
6050Sstevel@tonic-gate 			return (-1);
6060Sstevel@tonic-gate 
60712016SGirish.Moodalbail@Sun.COM 		mod = strrchr(modpath, '/');
60812016SGirish.Moodalbail@Sun.COM 		if (mod != NULL)
60912016SGirish.Moodalbail@Sun.COM 			mod++;
61012016SGirish.Moodalbail@Sun.COM 		else
61112016SGirish.Moodalbail@Sun.COM 			mod = modpath;
61212016SGirish.Moodalbail@Sun.COM 		if (ndd_str2proto(mod) == MOD_PROTO_NONE) {
61312016SGirish.Moodalbail@Sun.COM 			if ((fd = open(modpath, O_RDWR)) == -1) {
61412016SGirish.Moodalbail@Sun.COM 				printe(B_TRUE, "open of %s failed", modpath);
61512016SGirish.Moodalbail@Sun.COM 				continue;
61612016SGirish.Moodalbail@Sun.COM 			}
61712016SGirish.Moodalbail@Sun.COM 		} else {
61812016SGirish.Moodalbail@Sun.COM 			return (0);
6190Sstevel@tonic-gate 		}
6200Sstevel@tonic-gate 
62112016SGirish.Moodalbail@Sun.COM 		gldv3_warning(modpath);
6226512Ssowmini 
6230Sstevel@tonic-gate 		if (isastream(fd))
6240Sstevel@tonic-gate 			return (fd);
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 		(void) close(fd);
62712016SGirish.Moodalbail@Sun.COM 		printe(B_FALSE, "%s is not a streams device", modpath);
6280Sstevel@tonic-gate 	}
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate static void
fatal(char * fmt,...)6320Sstevel@tonic-gate fatal(char *fmt, ...)
6330Sstevel@tonic-gate {
6340Sstevel@tonic-gate 	va_list	ap;
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	va_start(ap, fmt);
6370Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, ap);
6380Sstevel@tonic-gate 	va_end(ap);
6390Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	exit(EXIT_FAILURE);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate static char *
errmsg(int error)6450Sstevel@tonic-gate errmsg(int error)
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate 	char *msg = strerror(error);
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	return (msg != NULL ? msg : "unknown error");
6500Sstevel@tonic-gate }
651