1*7836SJohn.Forte@Sun.COM /* 2*7836SJohn.Forte@Sun.COM * CDDL HEADER START 3*7836SJohn.Forte@Sun.COM * 4*7836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the 5*7836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License"). 6*7836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License. 7*7836SJohn.Forte@Sun.COM * 8*7836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*7836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions 11*7836SJohn.Forte@Sun.COM * and limitations under the License. 12*7836SJohn.Forte@Sun.COM * 13*7836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*7836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*7836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*7836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*7836SJohn.Forte@Sun.COM * 19*7836SJohn.Forte@Sun.COM * CDDL HEADER END 20*7836SJohn.Forte@Sun.COM */ 21*7836SJohn.Forte@Sun.COM /* 22*7836SJohn.Forte@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*7836SJohn.Forte@Sun.COM * Use is subject to license terms. 24*7836SJohn.Forte@Sun.COM */ 25*7836SJohn.Forte@Sun.COM 26*7836SJohn.Forte@Sun.COM #include <sys/types.h> 27*7836SJohn.Forte@Sun.COM #include <sys/utsname.h> 28*7836SJohn.Forte@Sun.COM #include <fcntl.h> 29*7836SJohn.Forte@Sun.COM #include <sys/param.h> 30*7836SJohn.Forte@Sun.COM #include <unistd.h> 31*7836SJohn.Forte@Sun.COM #include <stdarg.h> 32*7836SJohn.Forte@Sun.COM #include <errno.h> 33*7836SJohn.Forte@Sun.COM #include <stdio.h> 34*7836SJohn.Forte@Sun.COM #include <stdlib.h> 35*7836SJohn.Forte@Sun.COM #include <string.h> 36*7836SJohn.Forte@Sun.COM 37*7836SJohn.Forte@Sun.COM #include "libnsctl.h" 38*7836SJohn.Forte@Sun.COM #include <nsctl.h> 39*7836SJohn.Forte@Sun.COM #include <sys/ncall/ncall.h> 40*7836SJohn.Forte@Sun.COM 41*7836SJohn.Forte@Sun.COM 42*7836SJohn.Forte@Sun.COM 43*7836SJohn.Forte@Sun.COM /* 44*7836SJohn.Forte@Sun.COM * Internal routine to fetch all the current nodes that are 45*7836SJohn.Forte@Sun.COM * considered 'up'. 46*7836SJohn.Forte@Sun.COM * Returns the number of ncall_info structures that are valid 47*7836SJohn.Forte@Sun.COM * returned via the nodelist pointer, or -1 on an error. 48*7836SJohn.Forte@Sun.COM * If the call succeeds, then the memory returned via the 49*7836SJohn.Forte@Sun.COM * nodelist pointer needs to be freed by the caller. 50*7836SJohn.Forte@Sun.COM */ 51*7836SJohn.Forte@Sun.COM 52*7836SJohn.Forte@Sun.COM static int 53*7836SJohn.Forte@Sun.COM nsc_getcurrentnodes(ncall_node_t **nodelist) 54*7836SJohn.Forte@Sun.COM { 55*7836SJohn.Forte@Sun.COM ncall_node_t *mynodelist; 56*7836SJohn.Forte@Sun.COM int size; 57*7836SJohn.Forte@Sun.COM int fd; 58*7836SJohn.Forte@Sun.COM int rc = -1; 59*7836SJohn.Forte@Sun.COM int save_errno = 0; 60*7836SJohn.Forte@Sun.COM int ioctlcmd; 61*7836SJohn.Forte@Sun.COM 62*7836SJohn.Forte@Sun.COM if (nodelist == NULL) { 63*7836SJohn.Forte@Sun.COM errno = EINVAL; 64*7836SJohn.Forte@Sun.COM return (-1); 65*7836SJohn.Forte@Sun.COM } 66*7836SJohn.Forte@Sun.COM *nodelist = NULL; 67*7836SJohn.Forte@Sun.COM if ((fd = open("/dev/ncall", O_RDONLY)) < 0) { 68*7836SJohn.Forte@Sun.COM return (-1); 69*7836SJohn.Forte@Sun.COM } 70*7836SJohn.Forte@Sun.COM if ((size = ioctl(fd, NC_IOC_GETNETNODES, NULL)) < 1) { 71*7836SJohn.Forte@Sun.COM size = 1; 72*7836SJohn.Forte@Sun.COM ioctlcmd = NC_IOC_GETNODE; 73*7836SJohn.Forte@Sun.COM } else { 74*7836SJohn.Forte@Sun.COM ioctlcmd = NC_IOC_GETNETNODES; 75*7836SJohn.Forte@Sun.COM } 76*7836SJohn.Forte@Sun.COM 77*7836SJohn.Forte@Sun.COM mynodelist = malloc(size * sizeof (*mynodelist)); 78*7836SJohn.Forte@Sun.COM if (mynodelist == NULL) { 79*7836SJohn.Forte@Sun.COM save_errno = ENOMEM; 80*7836SJohn.Forte@Sun.COM } else { 81*7836SJohn.Forte@Sun.COM rc = ioctl(fd, ioctlcmd, mynodelist); 82*7836SJohn.Forte@Sun.COM if (rc < 0) { 83*7836SJohn.Forte@Sun.COM save_errno = errno; 84*7836SJohn.Forte@Sun.COM free(mynodelist); 85*7836SJohn.Forte@Sun.COM } else { 86*7836SJohn.Forte@Sun.COM /* fixup return value for single node ioctl */ 87*7836SJohn.Forte@Sun.COM if (ioctlcmd == NC_IOC_GETNODE) 88*7836SJohn.Forte@Sun.COM rc = 1; 89*7836SJohn.Forte@Sun.COM *nodelist = mynodelist; 90*7836SJohn.Forte@Sun.COM } 91*7836SJohn.Forte@Sun.COM } 92*7836SJohn.Forte@Sun.COM close(fd); 93*7836SJohn.Forte@Sun.COM errno = save_errno; 94*7836SJohn.Forte@Sun.COM return (rc); 95*7836SJohn.Forte@Sun.COM } 96*7836SJohn.Forte@Sun.COM 97*7836SJohn.Forte@Sun.COM 98*7836SJohn.Forte@Sun.COM /* 99*7836SJohn.Forte@Sun.COM * return the system id (the current value in the kernel 100*7836SJohn.Forte@Sun.COM * currently running). 101*7836SJohn.Forte@Sun.COM * 102*7836SJohn.Forte@Sun.COM * on error return -1 and set errno. 103*7836SJohn.Forte@Sun.COM */ 104*7836SJohn.Forte@Sun.COM int 105*7836SJohn.Forte@Sun.COM nsc_getsystemid(int *id) 106*7836SJohn.Forte@Sun.COM { 107*7836SJohn.Forte@Sun.COM ncall_node_t node; 108*7836SJohn.Forte@Sun.COM int rval = 0; 109*7836SJohn.Forte@Sun.COM int save_errno = 0; 110*7836SJohn.Forte@Sun.COM int fd; 111*7836SJohn.Forte@Sun.COM 112*7836SJohn.Forte@Sun.COM *id = 0; 113*7836SJohn.Forte@Sun.COM 114*7836SJohn.Forte@Sun.COM fd = open("/dev/ncall", O_RDONLY); 115*7836SJohn.Forte@Sun.COM if (fd < 0) 116*7836SJohn.Forte@Sun.COM return (-1); 117*7836SJohn.Forte@Sun.COM 118*7836SJohn.Forte@Sun.COM memset(&node, 0, sizeof (node)); 119*7836SJohn.Forte@Sun.COM 120*7836SJohn.Forte@Sun.COM rval = ioctl(fd, NC_IOC_GETNODE, &node); 121*7836SJohn.Forte@Sun.COM if (rval < 0) 122*7836SJohn.Forte@Sun.COM save_errno = errno; 123*7836SJohn.Forte@Sun.COM else { 124*7836SJohn.Forte@Sun.COM *id = node.nc_nodeid; 125*7836SJohn.Forte@Sun.COM /* 126*7836SJohn.Forte@Sun.COM * Return 0, not the mirror node id as returned 127*7836SJohn.Forte@Sun.COM * from the ioctl. 128*7836SJohn.Forte@Sun.COM */ 129*7836SJohn.Forte@Sun.COM rval = 0; 130*7836SJohn.Forte@Sun.COM } 131*7836SJohn.Forte@Sun.COM 132*7836SJohn.Forte@Sun.COM close(fd); 133*7836SJohn.Forte@Sun.COM 134*7836SJohn.Forte@Sun.COM errno = save_errno; 135*7836SJohn.Forte@Sun.COM return (rval); 136*7836SJohn.Forte@Sun.COM } 137*7836SJohn.Forte@Sun.COM 138*7836SJohn.Forte@Sun.COM 139*7836SJohn.Forte@Sun.COM /* 140*7836SJohn.Forte@Sun.COM * Runtime Solaris release checking. 141*7836SJohn.Forte@Sun.COM * 142*7836SJohn.Forte@Sun.COM * Compare the build release to the runtime release to check for an 143*7836SJohn.Forte@Sun.COM * acceptable match. 144*7836SJohn.Forte@Sun.COM * 145*7836SJohn.Forte@Sun.COM * Arguments: 146*7836SJohn.Forte@Sun.COM * build_ver - the string Solaris build release (e.g. "5.8") 147*7836SJohn.Forte@Sun.COM * map - optional array of nsc_release_t defining 148*7836SJohn.Forte@Sun.COM * acceptable build release / runtime release 149*7836SJohn.Forte@Sun.COM * matches. If supplied, must end will a NULL 150*7836SJohn.Forte@Sun.COM * array element. See src/head/nsctl.h for info. 151*7836SJohn.Forte@Sun.COM * reqd - used to return the required OS versions if the 152*7836SJohn.Forte@Sun.COM * return value is not -1. The returned string 153*7836SJohn.Forte@Sun.COM * is readonly. 154*7836SJohn.Forte@Sun.COM * 155*7836SJohn.Forte@Sun.COM * Returns: 156*7836SJohn.Forte@Sun.COM * TRUE - acceptable match 157*7836SJohn.Forte@Sun.COM * FALSE - no match (component should not continue to run) 158*7836SJohn.Forte@Sun.COM * -1 - error (errno is set) 159*7836SJohn.Forte@Sun.COM */ 160*7836SJohn.Forte@Sun.COM 161*7836SJohn.Forte@Sun.COM int 162*7836SJohn.Forte@Sun.COM nsc_check_release(const char *build_rel, nsc_release_t *map, char **reqd) 163*7836SJohn.Forte@Sun.COM { 164*7836SJohn.Forte@Sun.COM struct utsname uts; 165*7836SJohn.Forte@Sun.COM nsc_release_t *mp; 166*7836SJohn.Forte@Sun.COM const char *sep = ", "; 167*7836SJohn.Forte@Sun.COM char *cp, *tofree, *last; 168*7836SJohn.Forte@Sun.COM int rc; 169*7836SJohn.Forte@Sun.COM 170*7836SJohn.Forte@Sun.COM if (reqd) 171*7836SJohn.Forte@Sun.COM *reqd = NULL; 172*7836SJohn.Forte@Sun.COM 173*7836SJohn.Forte@Sun.COM if (build_rel == NULL || *build_rel == '\0') { 174*7836SJohn.Forte@Sun.COM errno = EINVAL; 175*7836SJohn.Forte@Sun.COM return (-1); 176*7836SJohn.Forte@Sun.COM } 177*7836SJohn.Forte@Sun.COM 178*7836SJohn.Forte@Sun.COM /* assume that build_rel is the required release for now */ 179*7836SJohn.Forte@Sun.COM if (reqd) 180*7836SJohn.Forte@Sun.COM *reqd = (char *)build_rel; 181*7836SJohn.Forte@Sun.COM 182*7836SJohn.Forte@Sun.COM if (uname(&uts) < 0) 183*7836SJohn.Forte@Sun.COM return (-1); 184*7836SJohn.Forte@Sun.COM 185*7836SJohn.Forte@Sun.COM /* build release == runtime release is always acceptable */ 186*7836SJohn.Forte@Sun.COM if (strcmp(build_rel, uts.release) == 0) 187*7836SJohn.Forte@Sun.COM return (TRUE); 188*7836SJohn.Forte@Sun.COM 189*7836SJohn.Forte@Sun.COM if (map == NULL) 190*7836SJohn.Forte@Sun.COM return (FALSE); 191*7836SJohn.Forte@Sun.COM 192*7836SJohn.Forte@Sun.COM rc = FALSE; 193*7836SJohn.Forte@Sun.COM tofree = NULL; 194*7836SJohn.Forte@Sun.COM 195*7836SJohn.Forte@Sun.COM for (mp = map; mp->build != NULL && mp->runtime != NULL; mp++) { 196*7836SJohn.Forte@Sun.COM if (strcmp(mp->build, build_rel) == 0) { 197*7836SJohn.Forte@Sun.COM /* 198*7836SJohn.Forte@Sun.COM * found an entry for this build release 199*7836SJohn.Forte@Sun.COM * - search for a match in the runtime releases 200*7836SJohn.Forte@Sun.COM */ 201*7836SJohn.Forte@Sun.COM 202*7836SJohn.Forte@Sun.COM /* reset reqd to this entry */ 203*7836SJohn.Forte@Sun.COM if (reqd) 204*7836SJohn.Forte@Sun.COM *reqd = (char *)mp->runtime; 205*7836SJohn.Forte@Sun.COM 206*7836SJohn.Forte@Sun.COM /* 207*7836SJohn.Forte@Sun.COM * operate on a copy of the string since strtok 208*7836SJohn.Forte@Sun.COM * is destructive. 209*7836SJohn.Forte@Sun.COM */ 210*7836SJohn.Forte@Sun.COM tofree = cp = strdup(mp->runtime); 211*7836SJohn.Forte@Sun.COM if (cp == NULL) { 212*7836SJohn.Forte@Sun.COM errno = ENOMEM; 213*7836SJohn.Forte@Sun.COM rc = -1; 214*7836SJohn.Forte@Sun.COM break; 215*7836SJohn.Forte@Sun.COM } 216*7836SJohn.Forte@Sun.COM 217*7836SJohn.Forte@Sun.COM cp = strtok_r(cp, sep, &last); 218*7836SJohn.Forte@Sun.COM while (cp != NULL) { 219*7836SJohn.Forte@Sun.COM if (strcmp(cp, uts.release) == 0) { 220*7836SJohn.Forte@Sun.COM rc = TRUE; 221*7836SJohn.Forte@Sun.COM break; 222*7836SJohn.Forte@Sun.COM } 223*7836SJohn.Forte@Sun.COM 224*7836SJohn.Forte@Sun.COM cp = strtok_r(NULL, sep, &last); 225*7836SJohn.Forte@Sun.COM } 226*7836SJohn.Forte@Sun.COM 227*7836SJohn.Forte@Sun.COM break; 228*7836SJohn.Forte@Sun.COM } 229*7836SJohn.Forte@Sun.COM } 230*7836SJohn.Forte@Sun.COM 231*7836SJohn.Forte@Sun.COM if (tofree) 232*7836SJohn.Forte@Sun.COM free(tofree); 233*7836SJohn.Forte@Sun.COM 234*7836SJohn.Forte@Sun.COM return (rc); 235*7836SJohn.Forte@Sun.COM } 236*7836SJohn.Forte@Sun.COM 237*7836SJohn.Forte@Sun.COM 238*7836SJohn.Forte@Sun.COM /* 239*7836SJohn.Forte@Sun.COM * return the system id corresponding to name 240*7836SJohn.Forte@Sun.COM * 241*7836SJohn.Forte@Sun.COM * on error return -1 and set errno. 242*7836SJohn.Forte@Sun.COM */ 243*7836SJohn.Forte@Sun.COM int 244*7836SJohn.Forte@Sun.COM nsc_name_to_id(char *name, int *id) 245*7836SJohn.Forte@Sun.COM { 246*7836SJohn.Forte@Sun.COM ncall_node_t *nodes; 247*7836SJohn.Forte@Sun.COM int rval = 0; 248*7836SJohn.Forte@Sun.COM int nodecnt; 249*7836SJohn.Forte@Sun.COM int slot; 250*7836SJohn.Forte@Sun.COM 251*7836SJohn.Forte@Sun.COM *id = 0; 252*7836SJohn.Forte@Sun.COM 253*7836SJohn.Forte@Sun.COM nodecnt = nsc_getcurrentnodes(&nodes); 254*7836SJohn.Forte@Sun.COM if (nodecnt < 0) { 255*7836SJohn.Forte@Sun.COM rval = -1; 256*7836SJohn.Forte@Sun.COM } else { 257*7836SJohn.Forte@Sun.COM for (slot = 0; slot < nodecnt; slot++) { 258*7836SJohn.Forte@Sun.COM if (strcmp(name, nodes[slot].nc_nodename) == 0) { 259*7836SJohn.Forte@Sun.COM *id = nodes[slot].nc_nodeid; 260*7836SJohn.Forte@Sun.COM break; 261*7836SJohn.Forte@Sun.COM } 262*7836SJohn.Forte@Sun.COM } 263*7836SJohn.Forte@Sun.COM if (slot >= nodecnt) { 264*7836SJohn.Forte@Sun.COM errno = ENOENT; 265*7836SJohn.Forte@Sun.COM rval = -1; 266*7836SJohn.Forte@Sun.COM } 267*7836SJohn.Forte@Sun.COM free(nodes); 268*7836SJohn.Forte@Sun.COM } 269*7836SJohn.Forte@Sun.COM return (rval); 270*7836SJohn.Forte@Sun.COM } 271*7836SJohn.Forte@Sun.COM 272*7836SJohn.Forte@Sun.COM /* 273*7836SJohn.Forte@Sun.COM * return the node name corresponding to system id 274*7836SJohn.Forte@Sun.COM * 275*7836SJohn.Forte@Sun.COM * on error return -1 and set errno. 276*7836SJohn.Forte@Sun.COM * The returned string has been strdup() and needs 277*7836SJohn.Forte@Sun.COM * to be freed by the caller. 278*7836SJohn.Forte@Sun.COM */ 279*7836SJohn.Forte@Sun.COM int 280*7836SJohn.Forte@Sun.COM nsc_id_to_name(char **name, int id) 281*7836SJohn.Forte@Sun.COM { 282*7836SJohn.Forte@Sun.COM ncall_node_t *nodes; 283*7836SJohn.Forte@Sun.COM int rval = 0; 284*7836SJohn.Forte@Sun.COM int nodecnt; 285*7836SJohn.Forte@Sun.COM int slot; 286*7836SJohn.Forte@Sun.COM char *foundname; 287*7836SJohn.Forte@Sun.COM 288*7836SJohn.Forte@Sun.COM *name = 0; 289*7836SJohn.Forte@Sun.COM foundname = NULL; 290*7836SJohn.Forte@Sun.COM 291*7836SJohn.Forte@Sun.COM nodecnt = nsc_getcurrentnodes(&nodes); 292*7836SJohn.Forte@Sun.COM if (nodecnt < 0) { 293*7836SJohn.Forte@Sun.COM rval = -1; 294*7836SJohn.Forte@Sun.COM } else { 295*7836SJohn.Forte@Sun.COM for (slot = 0; slot < nodecnt; slot++) { 296*7836SJohn.Forte@Sun.COM if (nodes[slot].nc_nodeid == id) { 297*7836SJohn.Forte@Sun.COM foundname = strdup(nodes[slot].nc_nodename); 298*7836SJohn.Forte@Sun.COM if (foundname) { 299*7836SJohn.Forte@Sun.COM *name = foundname; 300*7836SJohn.Forte@Sun.COM } else { 301*7836SJohn.Forte@Sun.COM errno = ENOMEM; 302*7836SJohn.Forte@Sun.COM rval = -1; 303*7836SJohn.Forte@Sun.COM } 304*7836SJohn.Forte@Sun.COM break; 305*7836SJohn.Forte@Sun.COM } 306*7836SJohn.Forte@Sun.COM } 307*7836SJohn.Forte@Sun.COM if (slot >= nodecnt) { 308*7836SJohn.Forte@Sun.COM errno = ENOENT; 309*7836SJohn.Forte@Sun.COM rval = -1; 310*7836SJohn.Forte@Sun.COM } 311*7836SJohn.Forte@Sun.COM free(nodes); 312*7836SJohn.Forte@Sun.COM } 313*7836SJohn.Forte@Sun.COM return (rval); 314*7836SJohn.Forte@Sun.COM } 315