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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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