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