changeset 10516:73cc1414bac0

6878550 libipmi: ipmi_user_iter() uses stale response data 6878552 libipmi: ipmi_get_user_name() issues wrong command 6878554 libipmi: ipmi_user_iter() needs to work with Sun ILOM
author Eric Schrock <Eric.Schrock@Sun.COM>
date Mon, 14 Sep 2009 10:13:26 -0700
parents 95e125dab827
children 43ea36a8f8b6
files usr/src/lib/libipmi/common/ipmi_user.c
diffstat 1 files changed, 46 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libipmi/common/ipmi_user.c	Mon Sep 14 08:35:38 2009 -0700
+++ b/usr/src/lib/libipmi/common/ipmi_user.c	Mon Sep 14 10:13:26 2009 -0700
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <libipmi.h>
 #include <string.h>
 
@@ -146,7 +144,7 @@
 	ipmi_cmd_t cmd, *resp;
 
 	cmd.ic_netfn = IPMI_NETFN_APP;
-	cmd.ic_cmd = IPMI_CMD_GET_USER_ACCESS;
+	cmd.ic_cmd = IPMI_CMD_GET_USER_NAME;
 	cmd.ic_lun = 0;
 	cmd.ic_data = &uid;
 	cmd.ic_dlen = sizeof (uid);
@@ -182,24 +180,43 @@
     void *data)
 {
 	ipmi_get_user_access_t *resp;
-	uint8_t i;
+	uint8_t i, uid_max;
 	ipmi_user_impl_t *uip;
 	ipmi_user_t *up;
 	const char *name;
+	uint8_t channel;
+	ipmi_deviceid_t *devid;
 
 	ipmi_user_clear(ihp);
 
+	channel = IPMI_USER_CHANNEL_CURRENT;
+
 	/*
-	 * First get the number of active users on the system by requesting the
-	 * reserved user ID (0).
+	 * Get the number of active users on the system by requesting the first
+	 * user ID (1).
 	 */
-	if ((resp = ipmi_get_user_access(ihp,
-	    IPMI_USER_CHANNEL_CURRENT, 0)) == NULL)
-		return (-1);
+	if ((resp = ipmi_get_user_access(ihp, channel, 1)) == NULL) {
+		/*
+		 * Some versions of the Sun ILOM have a bug which prevent the
+		 * GET USER ACCESS command from succeeding over the default
+		 * channel.  If this fails and we are on ILOM, then attempt to
+		 * use the standard channel (1) instead.
+		 */
+		if ((devid = ipmi_get_deviceid(ihp)) == NULL)
+			return (-1);
 
-	for (i = 1; i <= resp->igua_max_uid; i++) {
-		if ((resp = ipmi_get_user_access(ihp,
-		    IPMI_USER_CHANNEL_CURRENT, i)) == NULL)
+		if (!ipmi_is_sun_ilom(devid))
+			return (-1);
+
+		channel = 1;
+		if ((resp = ipmi_get_user_access(ihp, channel, 1)) == NULL)
+			return (-1);
+	}
+
+	uid_max = resp->igua_max_uid;
+	for (i = 1; i <= uid_max; i++) {
+		if (i != 1 && (resp = ipmi_get_user_access(ihp,
+		    channel, i)) == NULL)
 			return (-1);
 
 		if ((uip = ipmi_zalloc(ihp, sizeof (ipmi_user_impl_t))) == NULL)
@@ -215,11 +232,23 @@
 
 		ipmi_list_append(&ihp->ih_users, uip);
 
-		if ((name = ipmi_get_user_name(ihp, i)) == NULL)
-			return (-1);
+		/*
+		 * If we are requesting a username that doesn't have a
+		 * supported username, we may get an INVALID REQUEST response.
+		 * If this is the case, then continue as if there is no known
+		 * username.
+		 */
+		if ((name = ipmi_get_user_name(ihp, i)) == NULL) {
+			if (ipmi_errno(ihp) == EIPMI_INVALID_REQUEST)
+				continue;
+			else
+				return (-1);
+		}
 
-		if (*name != '\0' &&
-		    (up->iu_name = ipmi_strdup(ihp, name)) == NULL)
+		if (*name == '\0')
+			continue;
+
+		if ((up->iu_name = ipmi_strdup(ihp, name)) == NULL)
 			return (-1);
 	}