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
nsc_getcurrentnodes(ncall_node_t ** nodelist)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
nsc_getsystemid(int * id)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
nsc_check_release(const char * build_rel,nsc_release_t * map,char ** reqd)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
nsc_name_to_id(char * name,int * id)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
nsc_id_to_name(char ** name,int id)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