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*6e91bba0SGirish Moodalbail * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Copyright (c) 1990 Mentat Inc. 287c478bd9Sstevel@tonic-gate * ndd.c 2.1, last change 11/14/90 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <ctype.h> 347c478bd9Sstevel@tonic-gate #include <stdarg.h> 357c478bd9Sstevel@tonic-gate #include <fcntl.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <stropts.h> 39*6e91bba0SGirish Moodalbail #include <inet/tunables.h> 407c478bd9Sstevel@tonic-gate #include <inet/nd.h> 417c478bd9Sstevel@tonic-gate #include <string.h> 42*6e91bba0SGirish Moodalbail #include <strings.h> 437c478bd9Sstevel@tonic-gate #include <stdlib.h> 444045d941Ssowmini #include <libdllink.h> 454045d941Ssowmini #include <libintl.h> 46*6e91bba0SGirish Moodalbail #include <libipadm.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate static boolean_t do_getset(int fd, int cmd, char *buf, int buf_len); 497c478bd9Sstevel@tonic-gate static int get_value(char *msg, char *buf, int buf_len); 507c478bd9Sstevel@tonic-gate static void name_print(char *buf); 517c478bd9Sstevel@tonic-gate static void getset_interactive(int fd); 52a924b63fSVasumathi Sundaram - Sun Microsystems static int open_device(void); 537c478bd9Sstevel@tonic-gate static char *errmsg(int err); 547c478bd9Sstevel@tonic-gate static void fatal(char *fmt, ...); 557c478bd9Sstevel@tonic-gate static void printe(boolean_t print_errno, char *fmt, ...); 567c478bd9Sstevel@tonic-gate 57*6e91bba0SGirish Moodalbail static char modpath[128]; /* path to module */ 58*6e91bba0SGirish Moodalbail static char gbuf[65536]; /* need large buffer to retrieve all names */ 597c478bd9Sstevel@tonic-gate static char usage_str[] = "usage: ndd -set device_name name value\n" 607c478bd9Sstevel@tonic-gate " ndd [-get] device_name name [name ...]"; 617c478bd9Sstevel@tonic-gate 62149b7eb2SSowmini Varadhan /* 63*6e91bba0SGirish Moodalbail * Maps old ndd_name to the new ipadm_name. Any ndd property that is moved to 64*6e91bba0SGirish Moodalbail * libipadm should have an entry here to ensure backward compatibility 65*6e91bba0SGirish Moodalbail */ 66*6e91bba0SGirish Moodalbail typedef struct ndd2ipadm_map { 67*6e91bba0SGirish Moodalbail char *ndd_name; 68*6e91bba0SGirish Moodalbail char *ipadm_name; 69*6e91bba0SGirish Moodalbail uint_t ipadm_proto; 70*6e91bba0SGirish Moodalbail uint_t ipadm_flags; 71*6e91bba0SGirish Moodalbail uint_t ndd_perm; 72*6e91bba0SGirish Moodalbail } ndd2ipadm_map_t; 73*6e91bba0SGirish Moodalbail 74*6e91bba0SGirish Moodalbail static ndd2ipadm_map_t map[] = { 75*6e91bba0SGirish Moodalbail { "ip_def_ttl", "ttl", MOD_PROTO_IPV4, 0, 0 }, 76*6e91bba0SGirish Moodalbail { "ip6_def_hops", "hoplimit", MOD_PROTO_IPV6, 0, 0 }, 77*6e91bba0SGirish Moodalbail { "ip_forwarding", "forwarding", MOD_PROTO_IPV4, 0, 0 }, 78*6e91bba0SGirish Moodalbail { "ip6_forwarding", "forwarding", MOD_PROTO_IPV6, 0, 0 }, 79*6e91bba0SGirish Moodalbail { "icmp_recv_hiwat", "recv_maxbuf", MOD_PROTO_RAWIP, 0, 0 }, 80*6e91bba0SGirish Moodalbail { "icmp_xmit_hiwat", "send_maxbuf", MOD_PROTO_RAWIP, 0, 0 }, 81*6e91bba0SGirish Moodalbail { "tcp_ecn_permitted", "ecn", MOD_PROTO_TCP, 0, 0 }, 82*6e91bba0SGirish Moodalbail { "tcp_extra_priv_ports_add", "extra_priv_ports", MOD_PROTO_TCP, 83*6e91bba0SGirish Moodalbail IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE }, 84*6e91bba0SGirish Moodalbail { "tcp_extra_priv_ports_del", "extra_priv_ports", MOD_PROTO_TCP, 85*6e91bba0SGirish Moodalbail IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE }, 86*6e91bba0SGirish Moodalbail { "tcp_extra_priv_ports", "extra_priv_ports", MOD_PROTO_TCP, 87*6e91bba0SGirish Moodalbail 0, MOD_PROP_PERM_READ }, 88*6e91bba0SGirish Moodalbail { "tcp_largest_anon_port", "largest_anon_port", MOD_PROTO_TCP, 89*6e91bba0SGirish Moodalbail 0, 0 }, 90*6e91bba0SGirish Moodalbail { "tcp_recv_hiwat", "recv_maxbuf", MOD_PROTO_TCP, 0, 0 }, 91*6e91bba0SGirish Moodalbail { "tcp_sack_permitted", "sack", MOD_PROTO_TCP, 0, 0 }, 92*6e91bba0SGirish Moodalbail { "tcp_xmit_hiwat", "send_maxbuf", MOD_PROTO_TCP, 0, 0 }, 93*6e91bba0SGirish Moodalbail { "tcp_smallest_anon_port", "smallest_anon_port", MOD_PROTO_TCP, 94*6e91bba0SGirish Moodalbail 0, 0 }, 95*6e91bba0SGirish Moodalbail { "tcp_smallest_nonpriv_port", "smallest_nonpriv_port", MOD_PROTO_TCP, 96*6e91bba0SGirish Moodalbail 0, 0 }, 97*6e91bba0SGirish Moodalbail { "udp_extra_priv_ports_add", "extra_priv_ports", MOD_PROTO_UDP, 98*6e91bba0SGirish Moodalbail IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE }, 99*6e91bba0SGirish Moodalbail { "udp_extra_priv_ports_del", "extra_priv_ports", MOD_PROTO_UDP, 100*6e91bba0SGirish Moodalbail IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE }, 101*6e91bba0SGirish Moodalbail { "udp_extra_priv_ports", "extra_priv_ports", MOD_PROTO_UDP, 102*6e91bba0SGirish Moodalbail 0, MOD_PROP_PERM_READ }, 103*6e91bba0SGirish Moodalbail { "udp_largest_anon_port", "largest_anon_port", MOD_PROTO_UDP, 104*6e91bba0SGirish Moodalbail 0, 0 }, 105*6e91bba0SGirish Moodalbail { "udp_recv_hiwat", "recv_maxbuf", MOD_PROTO_UDP, 0, 0 }, 106*6e91bba0SGirish Moodalbail { "udp_xmit_hiwat", "send_maxbuf", MOD_PROTO_UDP, 0, 0 }, 107*6e91bba0SGirish Moodalbail { "udp_smallest_anon_port", "smallest_anon_port", MOD_PROTO_UDP, 108*6e91bba0SGirish Moodalbail 0, 0 }, 109*6e91bba0SGirish Moodalbail { "udp_smallest_nonpriv_port", "smallest_nonpriv_port", MOD_PROTO_UDP, 110*6e91bba0SGirish Moodalbail 0, 0 }, 111*6e91bba0SGirish Moodalbail { "sctp_extra_priv_ports_add", "extra_priv_ports", MOD_PROTO_SCTP, 112*6e91bba0SGirish Moodalbail IPADM_OPT_APPEND, MOD_PROP_PERM_WRITE }, 113*6e91bba0SGirish Moodalbail { "sctp_extra_priv_ports_del", "extra_priv_ports", MOD_PROTO_SCTP, 114*6e91bba0SGirish Moodalbail IPADM_OPT_REMOVE, MOD_PROP_PERM_WRITE }, 115*6e91bba0SGirish Moodalbail { "sctp_extra_priv_ports", "extra_priv_ports", MOD_PROTO_SCTP, 116*6e91bba0SGirish Moodalbail 0, MOD_PROP_PERM_READ }, 117*6e91bba0SGirish Moodalbail { "sctp_largest_anon_port", "largest_anon_port", MOD_PROTO_SCTP, 118*6e91bba0SGirish Moodalbail 0, 0 }, 119*6e91bba0SGirish Moodalbail { "sctp_recv_hiwat", "recv_maxbuf", MOD_PROTO_SCTP, 0, 0 }, 120*6e91bba0SGirish Moodalbail { "sctp_xmit_hiwat", "send_maxbuf", MOD_PROTO_SCTP, 0, 0 }, 121*6e91bba0SGirish Moodalbail { "sctp_smallest_anon_port", "smallest_anon_port", MOD_PROTO_SCTP, 122*6e91bba0SGirish Moodalbail 0, 0 }, 123*6e91bba0SGirish Moodalbail { "sctp_smallest_nonpriv_port", "smallest_nonpriv_port", MOD_PROTO_SCTP, 124*6e91bba0SGirish Moodalbail 0, 0 }, 125*6e91bba0SGirish Moodalbail { NULL, NULL, 0, 0, 0 } 126*6e91bba0SGirish Moodalbail }; 127*6e91bba0SGirish Moodalbail 128*6e91bba0SGirish Moodalbail static uint_t 129*6e91bba0SGirish Moodalbail ndd_str2proto(const char *protostr) 130*6e91bba0SGirish Moodalbail { 131*6e91bba0SGirish Moodalbail if (strcmp(protostr, "tcp") == 0 || 132*6e91bba0SGirish Moodalbail strcmp(protostr, "tcp6") == 0) { 133*6e91bba0SGirish Moodalbail return (MOD_PROTO_TCP); 134*6e91bba0SGirish Moodalbail } else if (strcmp(protostr, "udp") == 0 || 135*6e91bba0SGirish Moodalbail strcmp(protostr, "udp6") == 0) { 136*6e91bba0SGirish Moodalbail return (MOD_PROTO_UDP); 137*6e91bba0SGirish Moodalbail } else if (strcmp(protostr, "ip") == 0 || 138*6e91bba0SGirish Moodalbail strcmp(protostr, "ip6") == 0 || 139*6e91bba0SGirish Moodalbail strcmp(protostr, "arp") == 0) { 140*6e91bba0SGirish Moodalbail return (MOD_PROTO_IP); 141*6e91bba0SGirish Moodalbail } else if (strcmp(protostr, "icmp") == 0 || 142*6e91bba0SGirish Moodalbail strcmp(protostr, "icmp6") == 0) { 143*6e91bba0SGirish Moodalbail return (MOD_PROTO_RAWIP); 144*6e91bba0SGirish Moodalbail } else if (strcmp(protostr, "sctp") == 0 || 145*6e91bba0SGirish Moodalbail strcmp(protostr, "sctp6") == 0) { 146*6e91bba0SGirish Moodalbail return (MOD_PROTO_SCTP); 147*6e91bba0SGirish Moodalbail } 148*6e91bba0SGirish Moodalbail return (MOD_PROTO_NONE); 149*6e91bba0SGirish Moodalbail } 150*6e91bba0SGirish Moodalbail 151*6e91bba0SGirish Moodalbail static char * 152*6e91bba0SGirish Moodalbail ndd_perm2str(uint_t perm) 153*6e91bba0SGirish Moodalbail { 154*6e91bba0SGirish Moodalbail switch (perm) { 155*6e91bba0SGirish Moodalbail case MOD_PROP_PERM_READ: 156*6e91bba0SGirish Moodalbail return ("read only"); 157*6e91bba0SGirish Moodalbail case MOD_PROP_PERM_WRITE: 158*6e91bba0SGirish Moodalbail return ("write only"); 159*6e91bba0SGirish Moodalbail case MOD_PROP_PERM_RW: 160*6e91bba0SGirish Moodalbail return ("read and write"); 161*6e91bba0SGirish Moodalbail } 162*6e91bba0SGirish Moodalbail 163*6e91bba0SGirish Moodalbail return (NULL); 164*6e91bba0SGirish Moodalbail } 165*6e91bba0SGirish Moodalbail 166*6e91bba0SGirish Moodalbail /* 167*6e91bba0SGirish Moodalbail * This function converts any new property names to old ndd name by consulting 168*6e91bba0SGirish Moodalbail * ndd2ipadm_map_t. This is done to preserve backward compatibility. 169*6e91bba0SGirish Moodalbail */ 170*6e91bba0SGirish Moodalbail static void 171*6e91bba0SGirish Moodalbail print_ipadm2ndd(char *oldbuf, uint_t obufsize) 172*6e91bba0SGirish Moodalbail { 173*6e91bba0SGirish Moodalbail ndd2ipadm_map_t *nimap; 174*6e91bba0SGirish Moodalbail char *pname, *rwtag, *protostr; 175*6e91bba0SGirish Moodalbail uint_t proto, perm; 176*6e91bba0SGirish Moodalbail boolean_t matched; 177*6e91bba0SGirish Moodalbail 178*6e91bba0SGirish Moodalbail pname = oldbuf; 179*6e91bba0SGirish Moodalbail while (pname[0] && pname < (oldbuf + obufsize - 1)) { 180*6e91bba0SGirish Moodalbail for (protostr = pname; !isspace(*protostr); protostr++) 181*6e91bba0SGirish Moodalbail ; 182*6e91bba0SGirish Moodalbail *protostr++ = '\0'; 183*6e91bba0SGirish Moodalbail /* protostr now points to protocol */ 184*6e91bba0SGirish Moodalbail 185*6e91bba0SGirish Moodalbail for (rwtag = protostr; !isspace(*rwtag); rwtag++) 186*6e91bba0SGirish Moodalbail ; 187*6e91bba0SGirish Moodalbail *rwtag++ = '\0'; 188*6e91bba0SGirish Moodalbail /* rwtag now points to permissions */ 189*6e91bba0SGirish Moodalbail 190*6e91bba0SGirish Moodalbail proto = atoi(protostr); 191*6e91bba0SGirish Moodalbail perm = atoi(rwtag); 192*6e91bba0SGirish Moodalbail matched = B_FALSE; 193*6e91bba0SGirish Moodalbail for (nimap = map; nimap->ndd_name != NULL; nimap++) { 194*6e91bba0SGirish Moodalbail if (strcmp(pname, nimap->ipadm_name) != 0 || 195*6e91bba0SGirish Moodalbail !(nimap->ipadm_proto & proto)) 196*6e91bba0SGirish Moodalbail continue; 197*6e91bba0SGirish Moodalbail 198*6e91bba0SGirish Moodalbail matched = B_TRUE; 199*6e91bba0SGirish Moodalbail if (nimap->ndd_perm != 0) 200*6e91bba0SGirish Moodalbail perm = nimap->ndd_perm; 201*6e91bba0SGirish Moodalbail (void) printf("%-30s (%s)\n", nimap->ndd_name, 202*6e91bba0SGirish Moodalbail ndd_perm2str(perm)); 203*6e91bba0SGirish Moodalbail } 204*6e91bba0SGirish Moodalbail if (!matched) 205*6e91bba0SGirish Moodalbail (void) printf("%-30s (%s)\n", pname, 206*6e91bba0SGirish Moodalbail ndd_perm2str(perm)); 207*6e91bba0SGirish Moodalbail for (pname = rwtag; *pname++; ) 208*6e91bba0SGirish Moodalbail ; 209*6e91bba0SGirish Moodalbail } 210*6e91bba0SGirish Moodalbail } 211*6e91bba0SGirish Moodalbail 212*6e91bba0SGirish Moodalbail /* 213*6e91bba0SGirish Moodalbail * get/set the value for a given property by calling into libipadm. The 214*6e91bba0SGirish Moodalbail * IPH_LEGACY flag is used by libipadm for special handling. For some 215*6e91bba0SGirish Moodalbail * properties, libipadm.so displays strings (for e.g., on/off, 216*6e91bba0SGirish Moodalbail * never/passive/active, et al) instead of numerals. However ndd(1M) always 217*6e91bba0SGirish Moodalbail * printed numberals. This flag will help in avoiding printing strings. 218*6e91bba0SGirish Moodalbail */ 219*6e91bba0SGirish Moodalbail static boolean_t 220*6e91bba0SGirish Moodalbail do_ipadm_getset(int cmd, char *buf, int buflen) 221*6e91bba0SGirish Moodalbail { 222*6e91bba0SGirish Moodalbail ndd2ipadm_map_t *nimap; 223*6e91bba0SGirish Moodalbail ipadm_handle_t iph = NULL; 224*6e91bba0SGirish Moodalbail ipadm_status_t status; 225*6e91bba0SGirish Moodalbail char *mod; 226*6e91bba0SGirish Moodalbail uint_t proto, perm = 0, flags = 0; 227*6e91bba0SGirish Moodalbail char *pname, *pvalp; 228*6e91bba0SGirish Moodalbail int i; 229*6e91bba0SGirish Moodalbail 230*6e91bba0SGirish Moodalbail if ((mod = strrchr(modpath, '/')) == NULL) 231*6e91bba0SGirish Moodalbail mod = modpath; 232*6e91bba0SGirish Moodalbail else 233*6e91bba0SGirish Moodalbail ++mod; 234*6e91bba0SGirish Moodalbail if ((proto = ndd_str2proto(mod)) == MOD_PROTO_NONE) 235*6e91bba0SGirish Moodalbail return (B_FALSE); 236*6e91bba0SGirish Moodalbail 237*6e91bba0SGirish Moodalbail if ((status = ipadm_open(&iph, IPH_LEGACY)) != IPADM_SUCCESS) 238*6e91bba0SGirish Moodalbail goto fail; 239*6e91bba0SGirish Moodalbail 240*6e91bba0SGirish Moodalbail pname = buf; 241*6e91bba0SGirish Moodalbail for (nimap = map; nimap->ndd_name != NULL; nimap++) { 242*6e91bba0SGirish Moodalbail if (strcmp(pname, nimap->ndd_name) == 0) 243*6e91bba0SGirish Moodalbail break; 244*6e91bba0SGirish Moodalbail } 245*6e91bba0SGirish Moodalbail if (nimap->ndd_name != NULL) { 246*6e91bba0SGirish Moodalbail pname = nimap->ipadm_name; 247*6e91bba0SGirish Moodalbail proto = nimap->ipadm_proto; 248*6e91bba0SGirish Moodalbail flags = nimap->ipadm_flags; 249*6e91bba0SGirish Moodalbail perm = nimap->ndd_perm; 250*6e91bba0SGirish Moodalbail } 251*6e91bba0SGirish Moodalbail if (cmd == ND_GET) { 252*6e91bba0SGirish Moodalbail char propval[MAXPROPVALLEN], allprop[64536]; 253*6e91bba0SGirish Moodalbail uint_t pvalsz; 254*6e91bba0SGirish Moodalbail sa_family_t af = AF_UNSPEC; 255*6e91bba0SGirish Moodalbail int err; 256*6e91bba0SGirish Moodalbail 257*6e91bba0SGirish Moodalbail if (perm == MOD_PROP_PERM_WRITE) 258*6e91bba0SGirish Moodalbail fatal("operation failed: Permission denied"); 259*6e91bba0SGirish Moodalbail 260*6e91bba0SGirish Moodalbail if (strcmp(pname, "?") == 0) { 261*6e91bba0SGirish Moodalbail pvalp = allprop; 262*6e91bba0SGirish Moodalbail pvalsz = sizeof (allprop); 263*6e91bba0SGirish Moodalbail } else { 264*6e91bba0SGirish Moodalbail pvalp = propval; 265*6e91bba0SGirish Moodalbail pvalsz = sizeof (propval); 266*6e91bba0SGirish Moodalbail } 267*6e91bba0SGirish Moodalbail 268*6e91bba0SGirish Moodalbail status = ipadm_get_prop(iph, pname, pvalp, &pvalsz, proto, 269*6e91bba0SGirish Moodalbail IPADM_OPT_ACTIVE); 270*6e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) 271*6e91bba0SGirish Moodalbail goto fail; 272*6e91bba0SGirish Moodalbail 273*6e91bba0SGirish Moodalbail if (strcmp(pname, "?") == 0) { 274*6e91bba0SGirish Moodalbail (void) print_ipadm2ndd(pvalp, pvalsz); 275*6e91bba0SGirish Moodalbail } else { 276*6e91bba0SGirish Moodalbail char *tmp = pvalp; 277*6e91bba0SGirish Moodalbail 278*6e91bba0SGirish Moodalbail /* 279*6e91bba0SGirish Moodalbail * For backward compatibility if there are multiple 280*6e91bba0SGirish Moodalbail * values print each value in it's own line. 281*6e91bba0SGirish Moodalbail */ 282*6e91bba0SGirish Moodalbail while (*tmp != '\0') { 283*6e91bba0SGirish Moodalbail if (*tmp == ',') 284*6e91bba0SGirish Moodalbail *tmp = '\n'; 285*6e91bba0SGirish Moodalbail tmp++; 286*6e91bba0SGirish Moodalbail } 287*6e91bba0SGirish Moodalbail (void) printf("%s\n", pvalp); 288*6e91bba0SGirish Moodalbail } 289*6e91bba0SGirish Moodalbail (void) fflush(stdout); 290*6e91bba0SGirish Moodalbail } else { 291*6e91bba0SGirish Moodalbail if (perm == MOD_PROP_PERM_READ) 292*6e91bba0SGirish Moodalbail fatal("operation failed: Permission denied"); 293*6e91bba0SGirish Moodalbail 294*6e91bba0SGirish Moodalbail /* walk past the property name to find the property value */ 295*6e91bba0SGirish Moodalbail for (i = 0; buf[i] != '\0'; i++) 296*6e91bba0SGirish Moodalbail ; 297*6e91bba0SGirish Moodalbail 298*6e91bba0SGirish Moodalbail pvalp = &buf[++i]; 299*6e91bba0SGirish Moodalbail status = ipadm_set_prop(iph, pname, pvalp, proto, 300*6e91bba0SGirish Moodalbail flags|IPADM_OPT_ACTIVE); 301*6e91bba0SGirish Moodalbail } 302*6e91bba0SGirish Moodalbail fail: 303*6e91bba0SGirish Moodalbail ipadm_close(iph); 304*6e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) 305*6e91bba0SGirish Moodalbail fatal("operation failed: %s", ipadm_status2str(status)); 306*6e91bba0SGirish Moodalbail return (B_TRUE); 307*6e91bba0SGirish Moodalbail } 308*6e91bba0SGirish Moodalbail 309*6e91bba0SGirish Moodalbail /* 310149b7eb2SSowmini Varadhan * gldv3_warning() catches the case of /sbin/ndd abuse to administer 311149b7eb2SSowmini Varadhan * ethernet/MII props. Note that /sbin/ndd has not been abused 312149b7eb2SSowmini Varadhan * for administration of other datalink types, which makes it permissible 313149b7eb2SSowmini Varadhan * to test for support of the flowctrl property. 314149b7eb2SSowmini Varadhan */ 3154045d941Ssowmini static void 316a924b63fSVasumathi Sundaram - Sun Microsystems gldv3_warning(char *module) 3174045d941Ssowmini { 3184045d941Ssowmini datalink_id_t linkid; 3194045d941Ssowmini dladm_status_t status; 3204045d941Ssowmini char buf[DLADM_PROP_VAL_MAX], *cp; 321149b7eb2SSowmini Varadhan uint_t cnt = 1; 3224045d941Ssowmini char *link; 323a924b63fSVasumathi Sundaram - Sun Microsystems dladm_handle_t handle; 3244045d941Ssowmini 3254045d941Ssowmini link = strrchr(module, '/'); 3264045d941Ssowmini if (link == NULL) 3274045d941Ssowmini return; 328a924b63fSVasumathi Sundaram - Sun Microsystems 329a924b63fSVasumathi Sundaram - Sun Microsystems if (dladm_open(&handle) != DLADM_STATUS_OK) 330a924b63fSVasumathi Sundaram - Sun Microsystems return; 331a924b63fSVasumathi Sundaram - Sun Microsystems 3324ac67f02SAnurag S. Maskey status = dladm_name2info(handle, ++link, &linkid, NULL, NULL, NULL); 333a924b63fSVasumathi Sundaram - Sun Microsystems if (status == DLADM_STATUS_OK) { 3344045d941Ssowmini cp = buf; 335a924b63fSVasumathi Sundaram - Sun Microsystems status = dladm_get_linkprop(handle, linkid, 336a924b63fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_CURRENT, "flowctrl", &cp, &cnt); 337a924b63fSVasumathi Sundaram - Sun Microsystems if (status == DLADM_STATUS_OK) { 3384045d941Ssowmini (void) fprintf(stderr, gettext( 339a924b63fSVasumathi Sundaram - Sun Microsystems "WARNING: The ndd commands for datalink " 340a924b63fSVasumathi Sundaram - Sun Microsystems "administration are obsolete and may be " 341a924b63fSVasumathi Sundaram - Sun Microsystems "removed in a future release of Solaris. " 342a924b63fSVasumathi Sundaram - Sun Microsystems "Use dladm(1M) to manage datalink tunables.\n")); 343a924b63fSVasumathi Sundaram - Sun Microsystems } 344a924b63fSVasumathi Sundaram - Sun Microsystems } 345a924b63fSVasumathi Sundaram - Sun Microsystems dladm_close(handle); 3464045d941Ssowmini } 3474045d941Ssowmini 3487c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3497c478bd9Sstevel@tonic-gate int 3507c478bd9Sstevel@tonic-gate main(int argc, char **argv) 3517c478bd9Sstevel@tonic-gate { 352*6e91bba0SGirish Moodalbail char *cp, *value, *mod; 3537c478bd9Sstevel@tonic-gate int cmd; 354*6e91bba0SGirish Moodalbail int fd = 0; 3554045d941Ssowmini 3567c478bd9Sstevel@tonic-gate if (!(cp = *++argv)) { 357a924b63fSVasumathi Sundaram - Sun Microsystems while ((fd = open_device()) != -1) { 3587c478bd9Sstevel@tonic-gate getset_interactive(fd); 3597c478bd9Sstevel@tonic-gate (void) close(fd); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate return (EXIT_SUCCESS); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate cmd = ND_GET; 3657c478bd9Sstevel@tonic-gate if (cp[0] == '-') { 3667c478bd9Sstevel@tonic-gate if (strncmp(&cp[1], "set", 3) == 0) 3677c478bd9Sstevel@tonic-gate cmd = ND_SET; 3687c478bd9Sstevel@tonic-gate else if (strncmp(&cp[1], "get", 3) != 0) 3697c478bd9Sstevel@tonic-gate fatal(usage_str); 3707c478bd9Sstevel@tonic-gate if (!(cp = *++argv)) 3717c478bd9Sstevel@tonic-gate fatal(usage_str); 3727c478bd9Sstevel@tonic-gate } 373*6e91bba0SGirish Moodalbail 374a924b63fSVasumathi Sundaram - Sun Microsystems gldv3_warning(cp); 3754ac67f02SAnurag S. Maskey 376*6e91bba0SGirish Moodalbail mod = strrchr(cp, '/'); 377*6e91bba0SGirish Moodalbail if (mod != NULL) 378*6e91bba0SGirish Moodalbail mod++; 379*6e91bba0SGirish Moodalbail else 380*6e91bba0SGirish Moodalbail mod = cp; 381*6e91bba0SGirish Moodalbail 382*6e91bba0SGirish Moodalbail if (ndd_str2proto(mod) == MOD_PROTO_NONE) { 3837c478bd9Sstevel@tonic-gate if ((fd = open(cp, O_RDWR)) == -1) 3847c478bd9Sstevel@tonic-gate fatal("open of %s failed: %s", cp, errmsg(errno)); 3857c478bd9Sstevel@tonic-gate if (!isastream(fd)) 3867c478bd9Sstevel@tonic-gate fatal("%s is not a streams device", cp); 387*6e91bba0SGirish Moodalbail } 3887c478bd9Sstevel@tonic-gate 389*6e91bba0SGirish Moodalbail (void) strlcpy(modpath, cp, sizeof (modpath)); 3907c478bd9Sstevel@tonic-gate if (!(cp = *++argv)) { 3917c478bd9Sstevel@tonic-gate getset_interactive(fd); 3927c478bd9Sstevel@tonic-gate (void) close(fd); 3937c478bd9Sstevel@tonic-gate return (EXIT_SUCCESS); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate if (cmd == ND_SET) { 3977c478bd9Sstevel@tonic-gate if (!(value = *++argv)) 3987c478bd9Sstevel@tonic-gate fatal(usage_str); 3997c478bd9Sstevel@tonic-gate (void) snprintf(gbuf, sizeof (gbuf), "%s%c%s%c", cp, '\0', 4007c478bd9Sstevel@tonic-gate value, '\0'); 4017c478bd9Sstevel@tonic-gate if (!do_getset(fd, cmd, gbuf, sizeof (gbuf))) 4027c478bd9Sstevel@tonic-gate return (EXIT_FAILURE); 4037c478bd9Sstevel@tonic-gate } else { 4047c478bd9Sstevel@tonic-gate do { 4057c478bd9Sstevel@tonic-gate (void) memset(gbuf, '\0', sizeof (gbuf)); 4067c478bd9Sstevel@tonic-gate (void) strlcpy(gbuf, cp, sizeof (gbuf)); 4077c478bd9Sstevel@tonic-gate if (!do_getset(fd, cmd, gbuf, sizeof (gbuf))) 4087c478bd9Sstevel@tonic-gate return (EXIT_FAILURE); 4097c478bd9Sstevel@tonic-gate if (cp = *++argv) 4107c478bd9Sstevel@tonic-gate (void) putchar('\n'); 4117c478bd9Sstevel@tonic-gate } while (cp); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate (void) close(fd); 4157c478bd9Sstevel@tonic-gate return (EXIT_SUCCESS); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate static void 4197c478bd9Sstevel@tonic-gate name_print(char *buf) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate char *cp, *rwtag; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate for (cp = buf; cp[0]; ) { 4247c478bd9Sstevel@tonic-gate for (rwtag = cp; !isspace(*rwtag); rwtag++) 4257c478bd9Sstevel@tonic-gate ; 4267c478bd9Sstevel@tonic-gate *rwtag++ = '\0'; 4277c478bd9Sstevel@tonic-gate while (isspace(*rwtag)) 4287c478bd9Sstevel@tonic-gate rwtag++; 4297c478bd9Sstevel@tonic-gate (void) printf("%-30s%s\n", cp, rwtag); 4307c478bd9Sstevel@tonic-gate for (cp = rwtag; *cp++; ) 4317c478bd9Sstevel@tonic-gate ; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate * This function is vile, but it's better here than in the kernel. 4377c478bd9Sstevel@tonic-gate */ 4387c478bd9Sstevel@tonic-gate static boolean_t 4397c478bd9Sstevel@tonic-gate is_obsolete(const char *param) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate if (strcmp(param, "ip_enable_group_ifs") == 0 || 4427c478bd9Sstevel@tonic-gate strcmp(param, "ifgrp_status") == 0) { 4437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "The \"%s\" tunable has been superseded " 4447c478bd9Sstevel@tonic-gate "by IP Multipathing.\nPlease see the IP Network " 4457c478bd9Sstevel@tonic-gate "Multipathing Administration Guide for details.\n", param); 4467c478bd9Sstevel@tonic-gate return (B_TRUE); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate return (B_FALSE); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate static boolean_t 4527c478bd9Sstevel@tonic-gate do_getset(int fd, int cmd, char *buf, int buf_len) 4537c478bd9Sstevel@tonic-gate { 4547c478bd9Sstevel@tonic-gate char *cp; 4557c478bd9Sstevel@tonic-gate struct strioctl stri; 4567c478bd9Sstevel@tonic-gate boolean_t is_name_get; 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate if (is_obsolete(buf)) 4597c478bd9Sstevel@tonic-gate return (B_TRUE); 4607c478bd9Sstevel@tonic-gate 461*6e91bba0SGirish Moodalbail /* 462*6e91bba0SGirish Moodalbail * See if libipadm can handle this request, i.e., properties on 463*6e91bba0SGirish Moodalbail * following modules arp, ip, ipv4, ipv6, tcp, udp and sctp 464*6e91bba0SGirish Moodalbail */ 465*6e91bba0SGirish Moodalbail if (do_ipadm_getset(cmd, buf, buf_len)) 466*6e91bba0SGirish Moodalbail return (B_TRUE); 467*6e91bba0SGirish Moodalbail 4687c478bd9Sstevel@tonic-gate stri.ic_cmd = cmd; 4697c478bd9Sstevel@tonic-gate stri.ic_timout = 0; 4707c478bd9Sstevel@tonic-gate stri.ic_len = buf_len; 4717c478bd9Sstevel@tonic-gate stri.ic_dp = buf; 4727c478bd9Sstevel@tonic-gate is_name_get = stri.ic_cmd == ND_GET && buf[0] == '?' && buf[1] == '\0'; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate if (ioctl(fd, I_STR, &stri) == -1) { 4757c478bd9Sstevel@tonic-gate if (errno == ENOENT) 4767c478bd9Sstevel@tonic-gate (void) printf("name is non-existent for this module\n" 4777c478bd9Sstevel@tonic-gate "for a list of valid names, use name '?'\n"); 4787c478bd9Sstevel@tonic-gate else 4797c478bd9Sstevel@tonic-gate (void) printf("operation failed: %s\n", errmsg(errno)); 4807c478bd9Sstevel@tonic-gate return (B_FALSE); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate if (is_name_get) 4837c478bd9Sstevel@tonic-gate name_print(buf); 4847c478bd9Sstevel@tonic-gate else if (stri.ic_cmd == ND_GET) { 4857c478bd9Sstevel@tonic-gate for (cp = buf; *cp != '\0'; cp += strlen(cp) + 1) 4867c478bd9Sstevel@tonic-gate (void) puts(cp); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4897c478bd9Sstevel@tonic-gate return (B_TRUE); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate static int 4937c478bd9Sstevel@tonic-gate get_value(char *msg, char *buf, int buf_len) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate int len; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate (void) printf("%s", msg); 4987c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate buf[buf_len-1] = '\0'; 5017c478bd9Sstevel@tonic-gate if (fgets(buf, buf_len-1, stdin) == NULL) 5027c478bd9Sstevel@tonic-gate exit(EXIT_SUCCESS); 5037c478bd9Sstevel@tonic-gate len = strlen(buf); 5047c478bd9Sstevel@tonic-gate if (buf[len-1] == '\n') 5057c478bd9Sstevel@tonic-gate buf[len - 1] = '\0'; 5067c478bd9Sstevel@tonic-gate else 5077c478bd9Sstevel@tonic-gate len++; 5087c478bd9Sstevel@tonic-gate return (len); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate static void 5127c478bd9Sstevel@tonic-gate getset_interactive(int fd) 5137c478bd9Sstevel@tonic-gate { 5147c478bd9Sstevel@tonic-gate int cmd; 5157c478bd9Sstevel@tonic-gate char *cp; 5167c478bd9Sstevel@tonic-gate int len, buf_len; 5177c478bd9Sstevel@tonic-gate char len_buf[10]; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate for (;;) { 5207c478bd9Sstevel@tonic-gate (void) memset(gbuf, '\0', sizeof (gbuf)); 5217c478bd9Sstevel@tonic-gate len = get_value("name to get/set ? ", gbuf, sizeof (gbuf)); 5227c478bd9Sstevel@tonic-gate if (len == 1 || (gbuf[0] == 'q' && gbuf[1] == '\0')) 5237c478bd9Sstevel@tonic-gate return; 5247c478bd9Sstevel@tonic-gate for (cp = gbuf; cp < &gbuf[len]; cp++) { 5257c478bd9Sstevel@tonic-gate if (isspace(*cp)) 5267c478bd9Sstevel@tonic-gate *cp = '\0'; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate cmd = ND_GET; 5297c478bd9Sstevel@tonic-gate if (gbuf[0] != '?' && 5307c478bd9Sstevel@tonic-gate get_value("value ? ", &gbuf[len], sizeof (gbuf) - len) > 1) 5317c478bd9Sstevel@tonic-gate cmd = ND_SET; 5327c478bd9Sstevel@tonic-gate if (cmd == ND_GET && gbuf[0] != '?' && 5337c478bd9Sstevel@tonic-gate get_value("length ? ", len_buf, sizeof (len_buf)) > 1) { 5347c478bd9Sstevel@tonic-gate if (!isdigit(len_buf[0])) { 5357c478bd9Sstevel@tonic-gate (void) printf("invalid length\n"); 5367c478bd9Sstevel@tonic-gate continue; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate buf_len = atoi(len_buf); 5397c478bd9Sstevel@tonic-gate } else 5407c478bd9Sstevel@tonic-gate buf_len = sizeof (gbuf); 5417c478bd9Sstevel@tonic-gate (void) do_getset(fd, cmd, gbuf, buf_len); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate static void 5467c478bd9Sstevel@tonic-gate printe(boolean_t print_errno, char *fmt, ...) 5477c478bd9Sstevel@tonic-gate { 5487c478bd9Sstevel@tonic-gate va_list ap; 5497c478bd9Sstevel@tonic-gate int error = errno; 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate va_start(ap, fmt); 5527c478bd9Sstevel@tonic-gate (void) printf("*ERROR* "); 5537c478bd9Sstevel@tonic-gate (void) vprintf(fmt, ap); 5547c478bd9Sstevel@tonic-gate va_end(ap); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate if (print_errno) 5577c478bd9Sstevel@tonic-gate (void) printf(": %s\n", errmsg(error)); 5587c478bd9Sstevel@tonic-gate else 5597c478bd9Sstevel@tonic-gate (void) printf("\n"); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate static int 563a924b63fSVasumathi Sundaram - Sun Microsystems open_device() 5647c478bd9Sstevel@tonic-gate { 5657c478bd9Sstevel@tonic-gate int fd, len; 566*6e91bba0SGirish Moodalbail char *mod; 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate for (;;) { 569*6e91bba0SGirish Moodalbail len = get_value("module to query ? ", modpath, 570*6e91bba0SGirish Moodalbail sizeof (modpath)); 5717c478bd9Sstevel@tonic-gate if (len <= 1 || 572*6e91bba0SGirish Moodalbail (len == 2 && (modpath[0] == 'q' || modpath[0] == 'Q'))) 5737c478bd9Sstevel@tonic-gate return (-1); 5747c478bd9Sstevel@tonic-gate 575*6e91bba0SGirish Moodalbail mod = strrchr(modpath, '/'); 576*6e91bba0SGirish Moodalbail if (mod != NULL) 577*6e91bba0SGirish Moodalbail mod++; 578*6e91bba0SGirish Moodalbail else 579*6e91bba0SGirish Moodalbail mod = modpath; 580*6e91bba0SGirish Moodalbail if (ndd_str2proto(mod) == MOD_PROTO_NONE) { 581*6e91bba0SGirish Moodalbail if ((fd = open(modpath, O_RDWR)) == -1) { 582*6e91bba0SGirish Moodalbail printe(B_TRUE, "open of %s failed", modpath); 5837c478bd9Sstevel@tonic-gate continue; 5847c478bd9Sstevel@tonic-gate } 585*6e91bba0SGirish Moodalbail } else { 586*6e91bba0SGirish Moodalbail return (0); 587*6e91bba0SGirish Moodalbail } 5887c478bd9Sstevel@tonic-gate 589*6e91bba0SGirish Moodalbail gldv3_warning(modpath); 5904045d941Ssowmini 5917c478bd9Sstevel@tonic-gate if (isastream(fd)) 5927c478bd9Sstevel@tonic-gate return (fd); 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate (void) close(fd); 595*6e91bba0SGirish Moodalbail printe(B_FALSE, "%s is not a streams device", modpath); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate static void 6007c478bd9Sstevel@tonic-gate fatal(char *fmt, ...) 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate va_list ap; 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate va_start(ap, fmt); 6057c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap); 6067c478bd9Sstevel@tonic-gate va_end(ap); 6077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate static char * 6137c478bd9Sstevel@tonic-gate errmsg(int error) 6147c478bd9Sstevel@tonic-gate { 6157c478bd9Sstevel@tonic-gate char *msg = strerror(error); 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate return (msg != NULL ? msg : "unknown error"); 6187c478bd9Sstevel@tonic-gate } 619