summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/idmap/idmap/idmap.c31
-rw-r--r--usr/src/cmd/idmap/idmapd/Makefile15
-rw-r--r--usr/src/cmd/idmap/idmapd/adutils.c73
-rw-r--r--usr/src/cmd/idmap/idmapd/adutils.h28
-rw-r--r--usr/src/cmd/idmap/idmapd/dbutils.c589
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap.xml19
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap_config.c769
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap_config.h7
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap_lsa.c237
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap_lsa.h53
-rw-r--r--usr/src/cmd/idmap/idmapd/idmapd.c206
-rw-r--r--usr/src/cmd/idmap/idmapd/idmapd.h103
-rw-r--r--usr/src/cmd/idmap/idmapd/init.c38
-rw-r--r--usr/src/cmd/idmap/idmapd/nldaputils.c29
-rw-r--r--usr/src/cmd/idmap/idmapd/server.c165
-rw-r--r--usr/src/cmd/idmap/idmapd/wksids.c7
-rw-r--r--usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c386
-rw-r--r--usr/src/cmd/smbsrv/dtrace/cifs.d76
-rw-r--r--usr/src/cmd/smbsrv/dtrace/msrpc.d8
-rw-r--r--[-rwxr-xr-x]usr/src/cmd/smbsrv/dtrace/stype.d64
-rw-r--r--usr/src/cmd/smbsrv/smbadm/smbadm.c19
-rw-r--r--usr/src/cmd/smbsrv/smbd/Makefile6
-rw-r--r--usr/src/cmd/smbsrv/smbd/server.xml5
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd.h10
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c59
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_join.c5
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_main.c25
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_nicmon.c323
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c181
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_vss.c5
-rw-r--r--usr/src/cmd/smbsrv/smbstat/Makefile7
-rw-r--r--usr/src/cmd/smbsrv/smbstat/smbstat.c1298
32 files changed, 3648 insertions, 1198 deletions
diff --git a/usr/src/cmd/idmap/idmap/idmap.c b/usr/src/cmd/idmap/idmap/idmap.c
index 57c6b3bfe5..1c05e3d76a 100644
--- a/usr/src/cmd/idmap/idmap/idmap.c
+++ b/usr/src/cmd/idmap/idmap/idmap.c
@@ -117,6 +117,7 @@ id_code_t identity2code[] = {
#define n_FLAG 'n'
#define c_FLAG 'c'
#define v_FLAG 'v'
+#define V_FLAG 'V'
#define j_FLAG 'j'
@@ -256,7 +257,7 @@ static int do_get_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
static cmd_ops_t commands[] = {
{
"show",
- "c(create)v(verbose)",
+ "c(create)v(verbose)V(trace)",
do_show_mapping
},
{
@@ -1462,9 +1463,6 @@ print_how(idmap_how *how)
}
-
-
-
static
void
print_info(idmap_info *info)
@@ -1489,6 +1487,11 @@ print_info(idmap_info *info)
}
print_how(&info->how);
}
+
+ if (info->trace != NULL) {
+ (void) printf(gettext("Trace:\n"));
+ idmap_trace_print(stdout, "\t", info->trace);
+ }
}
@@ -1571,6 +1574,11 @@ print_error_info(idmap_info *info)
CHECK_NULL(how->idmap_how_u.idmu.value));
break;
}
+
+ if (info->trace != NULL) {
+ (void) printf(gettext("Trace:\n"));
+ idmap_trace_print(stderr, "\t", info->trace);
+ }
}
@@ -1627,7 +1635,7 @@ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
if (stat >= 0) {
(void) print_mapping(ph, nm);
- (void) print_how(&info.how);
+ print_how(&info.how);
idmap_info_free(&info);
}
name_mapping_fini(nm);
@@ -2952,8 +2960,13 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
return (-1);
}
- flag = f[c_FLAG] != NULL ? 0 : IDMAP_REQ_FLG_NO_NEW_ID_ALLOC;
- flag |= f[v_FLAG] == NULL ? 0 : IDMAP_REQ_FLG_MAPPING_INFO;
+ flag = 0;
+ if (f[c_FLAG] == NULL)
+ flag |= IDMAP_REQ_FLG_NO_NEW_ID_ALLOC;
+ if (f[v_FLAG] != NULL)
+ flag |= IDMAP_REQ_FLG_MAPPING_INFO;
+ if (f[V_FLAG] != NULL)
+ flag |= IDMAP_REQ_FLG_TRACE;
if (init_command())
return (-1);
@@ -3182,8 +3195,9 @@ errormsg:
print_error(pos, gettext("Error:\t%s\n"),
idmap_stat2string(handle, map_stat));
print_error_info(&info);
- } else
+ } else {
print_info(&info);
+ }
idmap_info_free(&info);
cleanup:
@@ -3546,7 +3560,6 @@ static
void
idmap_cli_logger(int pri, const char *format, ...)
{
- NOTE(ARGUNUSED(pri))
va_list args;
if (pri == LOG_DEBUG)
diff --git a/usr/src/cmd/idmap/idmapd/Makefile b/usr/src/cmd/idmap/idmapd/Makefile
index 04bee240ae..e940895ede 100644
--- a/usr/src/cmd/idmap/idmapd/Makefile
+++ b/usr/src/cmd/idmap/idmapd/Makefile
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG = idmapd
@@ -35,6 +34,7 @@ SERVEROBJS = \
idmap_config.o \
idmapd.o \
init.o \
+ idmap_lsa.o \
nldaputils.o \
rpc_svc.o \
server.o \
@@ -71,7 +71,8 @@ $(ROOTMANIFEST) := FILEMODE= 444
INCS += -I. -I../../../lib/libidmap/common\
-I../../../lib/libsldap/common\
- -I../../../lib/libadutils/common
+ -I../../../lib/libadutils/common \
+ -I../../../lib/smbsrv/libsmb/common
$(OBJS) := CPPFLAGS += $(INCS) -D_REENTRANT
$(POFILE) := CPPFLAGS += $(INCS)
@@ -86,12 +87,16 @@ LDLIBS += -lsecdb \
-lldap \
-luuid \
-ladutils \
- -lumem
+ -lumem \
+ -lnvpair \
+ -L $(ROOT)/usr/lib/smbsrv \
+ -lsmb
rpc_svc.o := CFLAGS += $(RPC_MSGOUT_OPT)
$(PROG) := MAPFILES = $(MAPFILE.INT) $(MAPFILE.NGB)
-$(PROG) := LDFLAGS += $(MAPFILES:%=-M%)
+$(PROG) := LDFLAGS += $(MAPFILES:%=-M%) \
+ -R /usr/lib/smbsrv
DIRMODE = 0755
FILEMODE = 0555
diff --git a/usr/src/cmd/idmap/idmapd/adutils.c b/usr/src/cmd/idmap/idmapd/adutils.c
index cbc447e0c9..254ccc214d 100644
--- a/usr/src/cmd/idmap/idmapd/adutils.c
+++ b/usr/src/cmd/idmap/idmapd/adutils.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -78,13 +77,13 @@ typedef struct idmap_q {
*/
char *ecanonname; /* expected canon name */
char *edomain; /* expected domain name */
- int eunixtype; /* expected unix type */
+ idmap_id_type esidtype; /* expected SID type */
/* results */
char **canonname; /* actual canon name */
char **domain; /* name of domain of object */
char **sid; /* stringified SID */
rid_t *rid; /* RID */
- int *sid_type; /* user or group SID? */
+ idmap_id_type *sid_type; /* user or group SID? */
char **unixname; /* unixname for name mapping */
char **dn; /* DN of entry */
char **attr; /* Attr for name mapping */
@@ -352,7 +351,7 @@ idmap_bv_objclass2sidtype(BerValue **bvalues, int *sid_type)
{
BerValue **cbval;
- *sid_type = _IDMAP_T_OTHER;
+ *sid_type = IDMAP_SID;
if (bvalues == NULL)
return (0);
@@ -363,14 +362,14 @@ idmap_bv_objclass2sidtype(BerValue **bvalues, int *sid_type)
*/
for (cbval = bvalues; *cbval != NULL; cbval++) {
if (BVAL_CASEEQ(cbval, "group")) {
- *sid_type = _IDMAP_T_GROUP;
+ *sid_type = IDMAP_GSID;
break;
} else if (BVAL_CASEEQ(cbval, "user")) {
- *sid_type = _IDMAP_T_USER;
+ *sid_type = IDMAP_USID;
break;
}
/*
- * "else if (*sid_type = _IDMAP_T_USER)" then this is a
+ * "else if (*sid_type = IDMAP_USID)" then this is a
* new sub-class of user -- what to do with it??
*/
}
@@ -426,9 +425,9 @@ idmap_extract_object(idmap_query_state_t *state, idmap_q_t *q,
if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU &&
q->pid != NULL) {
- if (sid_type == _IDMAP_T_USER)
+ if (sid_type == IDMAP_USID)
attr = UIDNUMBER;
- else if (sid_type == _IDMAP_T_GROUP)
+ else if (sid_type == IDMAP_GSID)
attr = GIDNUMBER;
if (attr != NULL) {
bvalues = ldap_get_values_len(ld, res, attr);
@@ -451,24 +450,20 @@ idmap_extract_object(idmap_query_state_t *state, idmap_q_t *q,
* AD attribute name that will have the unixname, and retrieve
* its value.
*/
- int unix_type;
+ idmap_id_type esidtype;
/*
- * Determine the target UNIX type.
+ * Determine the target type.
*
* If the caller specified one, use that. Otherwise, give the
* same type that as we found for the Windows user.
*/
- unix_type = q->eunixtype;
- if (unix_type == _IDMAP_T_UNDEF) {
- if (sid_type == _IDMAP_T_USER)
- unix_type = _IDMAP_T_USER;
- else if (sid_type == _IDMAP_T_GROUP)
- unix_type = _IDMAP_T_GROUP;
- }
+ esidtype = q->esidtype;
+ if (esidtype == IDMAP_SID)
+ esidtype = sid_type;
- if (unix_type == _IDMAP_T_USER)
+ if (esidtype == IDMAP_USID)
attr = state->ad_unixuser_attr;
- else if (unix_type == _IDMAP_T_GROUP)
+ else if (esidtype == IDMAP_GSID)
attr = state->ad_unixgroup_attr;
if (attr != NULL) {
@@ -591,10 +586,10 @@ idmap_lookup_batch_end(idmap_query_state_t **state)
static
idmap_retcode
idmap_batch_add1(idmap_query_state_t *state, const char *filter,
- char *ecanonname, char *edomain, int eunixtype,
+ char *ecanonname, char *edomain, idmap_id_type esidtype,
char **dn, char **attr, char **value,
char **canonname, char **dname,
- char **sid, rid_t *rid, int *sid_type, char **unixname,
+ char **sid, rid_t *rid, idmap_id_type *sid_type, char **unixname,
posix_id_t *pid,
idmap_retcode *rc)
{
@@ -614,7 +609,7 @@ idmap_batch_add1(idmap_query_state_t *state, const char *filter,
*/
q->ecanonname = ecanonname;
q->edomain = edomain;
- q->eunixtype = eunixtype;
+ q->esidtype = esidtype;
/* Remember where to put the results */
q->canonname = canonname;
@@ -637,18 +632,18 @@ idmap_batch_add1(idmap_query_state_t *state, const char *filter,
if (unixname != NULL) {
/* Add unixuser/unixgroup attribute names to the attrs list */
- if (eunixtype != _IDMAP_T_GROUP &&
+ if (esidtype != IDMAP_GSID &&
state->ad_unixuser_attr != NULL)
attrs[i++] = (char *)state->ad_unixuser_attr;
- if (eunixtype != _IDMAP_T_USER &&
+ if (esidtype != IDMAP_USID &&
state->ad_unixgroup_attr != NULL)
attrs[i++] = (char *)state->ad_unixgroup_attr;
}
if (pid != NULL) {
- if (eunixtype != _IDMAP_T_GROUP)
+ if (esidtype != IDMAP_GSID)
attrs[i++] = UIDNUMBER;
- if (eunixtype != _IDMAP_T_USER)
+ if (esidtype != IDMAP_USID)
attrs[i++] = GIDNUMBER;
}
@@ -667,7 +662,7 @@ idmap_batch_add1(idmap_query_state_t *state, const char *filter,
*/
*rc = IDMAP_ERR_RETRIABLE_NET_ERR;
if (sid_type != NULL)
- *sid_type = _IDMAP_T_OTHER;
+ *sid_type = IDMAP_SID;
if (sid != NULL)
*sid = NULL;
if (dname != NULL)
@@ -698,10 +693,10 @@ idmap_batch_add1(idmap_query_state_t *state, const char *filter,
idmap_retcode
idmap_name2sid_batch_add1(idmap_query_state_t *state,
- const char *name, const char *dname, int eunixtype,
+ const char *name, const char *dname, idmap_id_type esidtype,
char **dn, char **attr, char **value,
char **canonname, char **sid, rid_t *rid,
- int *sid_type, char **unixname,
+ idmap_id_type *sid_type, char **unixname,
posix_id_t *pid, idmap_retcode *rc)
{
idmap_retcode retcode;
@@ -761,7 +756,7 @@ idmap_name2sid_batch_add1(idmap_query_state_t *state,
}
retcode = idmap_batch_add1(state, filter, ecanonname, edomain,
- eunixtype, dn, attr, value, canonname, NULL, sid, rid, sid_type,
+ esidtype, dn, attr, value, canonname, NULL, sid, rid, sid_type,
unixname, pid, rc);
free(filter);
@@ -771,9 +766,9 @@ idmap_name2sid_batch_add1(idmap_query_state_t *state,
idmap_retcode
idmap_sid2name_batch_add1(idmap_query_state_t *state,
- const char *sid, const rid_t *rid, int eunixtype,
+ const char *sid, const rid_t *rid, idmap_id_type esidtype,
char **dn, char **attr, char **value,
- char **name, char **dname, int *sid_type,
+ char **name, char **dname, idmap_id_type *sid_type,
char **unixname, posix_id_t *pid, idmap_retcode *rc)
{
idmap_retcode retcode;
@@ -801,7 +796,7 @@ idmap_sid2name_batch_add1(idmap_query_state_t *state,
if (filter == NULL)
return (IDMAP_ERR_MEMORY);
- retcode = idmap_batch_add1(state, filter, NULL, NULL, eunixtype,
+ retcode = idmap_batch_add1(state, filter, NULL, NULL, esidtype,
dn, attr, value, name, dname, NULL, NULL, sid_type, unixname,
pid, rc);
@@ -815,7 +810,7 @@ idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
const char *unixname, int is_user, int is_wuser,
char **dn, char **attr, char **value,
char **sid, rid_t *rid, char **name,
- char **dname, int *sid_type, idmap_retcode *rc)
+ char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
{
idmap_retcode retcode;
char *filter, *s_unixname;
@@ -841,7 +836,7 @@ idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
}
retcode = idmap_batch_add1(state, filter, NULL, NULL,
- _IDMAP_T_UNDEF, dn, NULL, NULL, name, dname, sid, rid, sid_type,
+ IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
NULL, NULL, rc);
if (retcode == IDMAP_SUCCESS && attr != NULL) {
@@ -864,7 +859,7 @@ idmap_pid2sid_batch_add1(idmap_query_state_t *state,
posix_id_t pid, int is_user,
char **dn, char **attr, char **value,
char **sid, rid_t *rid, char **name,
- char **dname, int *sid_type, idmap_retcode *rc)
+ char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
{
idmap_retcode retcode;
char *filter;
@@ -882,7 +877,7 @@ idmap_pid2sid_batch_add1(idmap_query_state_t *state,
return (IDMAP_ERR_MEMORY);
retcode = idmap_batch_add1(state, filter, NULL, NULL,
- _IDMAP_T_UNDEF, dn, NULL, NULL, name, dname, sid, rid, sid_type,
+ IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
NULL, NULL, rc);
if (retcode == IDMAP_SUCCESS && attr != NULL) {
diff --git a/usr/src/cmd/idmap/idmapd/adutils.h b/usr/src/cmd/idmap/idmapd/adutils.h
index 88807f01d8..b5d45b4a4d 100644
--- a/usr/src/cmd/idmap/idmapd/adutils.h
+++ b/usr/src/cmd/idmap/idmapd/adutils.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _ADUTILS_H
@@ -56,16 +55,6 @@ extern "C" {
* idmapd interfaces stolen? from other idmapd code?
*/
-/*
- * Eventually these should be an enum here, but instead we share a
- * namespace with other things in idmapd.
- */
-#define _IDMAP_T_OTHER 0
-#define _IDMAP_T_UNDEF -1
-#define _IDMAP_T_USER -1004
-#define _IDMAP_T_GROUP -1005
-#define _IDMAP_T_DOMAIN -1006
-
typedef uint32_t rid_t;
typedef uid_t posix_id_t;
@@ -118,9 +107,10 @@ void idmap_lookup_release_batch(idmap_query_state_t **state);
* The caller must free() *sid.
*/
idmap_retcode idmap_name2sid_batch_add1(idmap_query_state_t *state,
- const char *name, const char *dname, int eunixtype,
+ const char *name, const char *dname, idmap_id_type esidtype,
char **dn, char **attr, char **value, char **canonname,
- char **sid, rid_t *rid, int *sid_type, char **unixname,
+ char **sid, rid_t *rid, idmap_id_type *sid_type,
+ char **unixname,
posix_id_t *pid, idmap_retcode *rc);
/*
* Add a SID->name lookup
@@ -137,9 +127,9 @@ idmap_retcode idmap_name2sid_batch_add1(idmap_query_state_t *state,
* The caller must free() *name and *dname (if present).
*/
idmap_retcode idmap_sid2name_batch_add1(idmap_query_state_t *state,
- const char *sid, const rid_t *rid, int eunixtype,
+ const char *sid, const rid_t *rid, idmap_id_type esidtype,
char **dn, char **attr, char **value, char **name,
- char **dname, int *sid_type, char **unixname,
+ char **dname, idmap_id_type *sid_type, char **unixname,
posix_id_t *pid, idmap_retcode *rc);
/*
@@ -148,7 +138,8 @@ idmap_retcode idmap_sid2name_batch_add1(idmap_query_state_t *state,
idmap_retcode idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
const char *unixname, int is_user, int is_wuser,
char **dn, char **attr, char **value, char **sid, rid_t *rid,
- char **name, char **dname, int *sid_type, idmap_retcode *rc);
+ char **name, char **dname, idmap_id_type *sid_type,
+ idmap_retcode *rc);
/*
* Add a PID->SID lookup
@@ -156,7 +147,8 @@ idmap_retcode idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
idmap_retcode idmap_pid2sid_batch_add1(idmap_query_state_t *state,
posix_id_t pid, int is_user,
char **dn, char **attr, char **value, char **sid, rid_t *rid,
- char **name, char **dname, int *sid_type, idmap_retcode *rc);
+ char **name, char **dname, idmap_id_type *sid_type,
+ idmap_retcode *rc);
/*
* Set unixname attribute names for the batch for AD-based name mapping
diff --git a/usr/src/cmd/idmap/idmapd/dbutils.c b/usr/src/cmd/idmap/idmapd/dbutils.c
index 3043c507db..d697ab154a 100644
--- a/usr/src/cmd/idmap/idmapd/dbutils.c
+++ b/usr/src/cmd/idmap/idmapd/dbutils.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -42,6 +41,7 @@
#include <assert.h>
#include <sys/u8_textprep.h>
#include <alloca.h>
+#include <note.h>
#include "idmapd.h"
#include "adutils.h"
@@ -49,6 +49,7 @@
#include "idmap_priv.h"
#include "schema.h"
#include "nldaputils.h"
+#include "idmap_lsa.h"
#include "miscutils.h"
@@ -56,7 +57,7 @@ static idmap_retcode sql_compile_n_step_once(sqlite *, char *,
sqlite_vm **, int *, int, const char ***);
static idmap_retcode lookup_localsid2pid(idmap_mapping *, idmap_id_res *);
static idmap_retcode lookup_cache_name2sid(sqlite *, const char *,
- const char *, char **, char **, idmap_rid_t *, int *);
+ const char *, char **, char **, idmap_rid_t *, idmap_id_type *);
#define NELEM(a) (sizeof (a) / sizeof ((a)[0]))
@@ -129,10 +130,13 @@ idmap_tsd_destroy(void *key)
}
}
-int
+void
idmap_init_tsd_key(void)
{
- return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy));
+ int rc;
+
+ rc = pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy);
+ assert(rc == 0);
}
@@ -1412,7 +1416,7 @@ lookup_wksids_name2sid(
char **canondomain,
char **sidprefix,
idmap_rid_t *rid,
- int *type)
+ idmap_id_type *type)
{
const wksids_table_t *wksid;
@@ -1463,7 +1467,7 @@ lookup_wksids_name2sid(
if (type != NULL)
*type = (wksid->is_wuser) ?
- _IDMAP_T_USER : _IDMAP_T_GROUP;
+ IDMAP_USID : IDMAP_GSID;
return (IDMAP_SUCCESS);
@@ -1702,10 +1706,36 @@ out:
return (retcode);
}
+/*
+ * Previous versions used two enumerations for representing types.
+ * One of those has largely been eliminated, but was used in the
+ * name cache table and so during an upgrade might still be visible.
+ * In addition, the test suite prepopulates the cache with these values.
+ *
+ * This function translates those old values into the new values.
+ *
+ * This code deliberately does not use symbolic values for the legacy
+ * values. This is the *only* place where they should be used.
+ */
+static
+idmap_id_type
+xlate_legacy_type(int type)
+{
+ switch (type) {
+ case -1004: /* _IDMAP_T_USER */
+ return (IDMAP_USID);
+ case -1005: /* _IDMAP_T_GROUP */
+ return (IDMAP_GSID);
+ default:
+ return (type);
+ }
+ NOTE(NOTREACHED)
+}
+
static
idmap_retcode
lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid,
- char **canonname, char **canondomain, int *type)
+ char **canonname, char **canondomain, idmap_id_type *type)
{
char *end;
char *sql = NULL;
@@ -1745,7 +1775,7 @@ lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid,
retcode = IDMAP_ERR_CACHE;
goto out;
}
- *type = strtol(values[2], &end, 10);
+ *type = xlate_legacy_type(strtol(values[2], &end, 10));
}
if (canonname != NULL && values[0] != NULL) {
@@ -1785,15 +1815,17 @@ static
idmap_retcode
lookup_name_cache(sqlite *cache, idmap_mapping *req, idmap_id_res *res)
{
- int type = -1;
+ idmap_id_type type = -1;
idmap_retcode retcode;
char *sidprefix = NULL;
idmap_rid_t rid;
char *name = NULL, *domain = NULL;
/* Done if we've both sid and winname */
- if (req->id1.idmap_id_u.sid.prefix != NULL && req->id1name != NULL)
+ if (req->id1.idmap_id_u.sid.prefix != NULL && req->id1name != NULL) {
+ /* Don't bother TRACE()ing, too boring */
return (IDMAP_SUCCESS);
+ }
if (req->id1.idmap_id_u.sid.prefix != NULL) {
/* Lookup sid to winname */
@@ -1807,18 +1839,18 @@ lookup_name_cache(sqlite *cache, idmap_mapping *req, idmap_id_res *res)
}
if (retcode != IDMAP_SUCCESS) {
+ if (retcode == IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res, "Not found in name cache");
+ } else {
+ TRACE(req, res, "Name cache lookup error=%d", retcode);
+ }
free(name);
free(domain);
free(sidprefix);
return (retcode);
}
- if (res->id.idtype == IDMAP_POSIXID) {
- res->id.idtype = (type == _IDMAP_T_USER) ?
- IDMAP_UID : IDMAP_GID;
- }
- req->id1.idtype = (type == _IDMAP_T_USER) ?
- IDMAP_USID : IDMAP_GSID;
+ req->id1.idtype = type;
req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE;
@@ -1839,6 +1871,8 @@ lookup_name_cache(sqlite *cache, idmap_mapping *req, idmap_id_res *res)
req->id1.idmap_id_u.sid.prefix = sidprefix;
req->id1.idmap_id_u.sid.rid = rid;
}
+
+ TRACE(req, res, "Found in name cache");
return (retcode);
}
@@ -1852,7 +1886,7 @@ ad_lookup_batch_int(lookup_state_t *state, idmap_mapping_batch *batch,
idmap_retcode retcode;
int i, num_queued, is_wuser, is_user;
int next_request;
- int retries = 0, eunixtype;
+ int retries = 0, esidtype;
char **unixname;
idmap_mapping *req;
idmap_id_res *res;
@@ -1928,23 +1962,23 @@ retry:
if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR)
continue;
- if (IS_REQUEST_SID(*req, 1)) {
+ if (IS_ID_SID(req->id1)) {
/* win2unix request: */
posix_id_t *pid = NULL;
unixname = dn = attr = value = NULL;
- eunixtype = _IDMAP_T_UNDEF;
+ esidtype = IDMAP_SID;
if (state->directory_based_mapping ==
DIRECTORY_MAPPING_NAME &&
req->id2name == NULL) {
if (res->id.idtype == IDMAP_UID &&
AD_OR_MIXED(state->nm_siduid)) {
- eunixtype = _IDMAP_T_USER;
+ esidtype = IDMAP_USID;
unixname = &req->id2name;
} else if (res->id.idtype == IDMAP_GID &&
AD_OR_MIXED(state->nm_sidgid)) {
- eunixtype = _IDMAP_T_GROUP;
+ esidtype = IDMAP_GSID;
unixname = &req->id2name;
} else if (AD_OR_MIXED(state->nm_siduid) ||
AD_OR_MIXED(state->nm_sidgid)) {
@@ -1957,7 +1991,7 @@ retry:
* mapping only if AD or MIXED
* mode is enabled.
*/
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
res->info.src = IDMAP_MAP_SRC_NEW;
how->map_type = IDMAP_MAP_TYPE_DS_AD;
dn = &how->idmap_how_u.ad.dn;
@@ -1975,7 +2009,7 @@ retry:
/*
* Get how info for IDMU based mapping.
*/
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
res->info.src = IDMAP_MAP_SRC_NEW;
how->map_type = IDMAP_MAP_TYPE_IDMU;
dn = &how->idmap_how_u.idmu.dn;
@@ -1987,13 +2021,13 @@ retry:
/* Lookup AD by SID */
retcode = idmap_sid2name_batch_add1(
qs, req->id1.idmap_id_u.sid.prefix,
- &req->id1.idmap_id_u.sid.rid, eunixtype,
+ &req->id1.idmap_id_u.sid.rid, esidtype,
dn, attr, value,
(req->id1name == NULL) ?
&req->id1name : NULL,
(req->id1domain == NULL) ?
&req->id1domain : NULL,
- (int *)&req->id2.idtype, unixname,
+ &req->id2.idtype, unixname,
pid,
&res->retcode);
if (retcode == IDMAP_SUCCESS)
@@ -2003,19 +2037,19 @@ retry:
assert(req->id1name != NULL);
retcode = idmap_name2sid_batch_add1(
qs, req->id1name, req->id1domain,
- eunixtype,
+ esidtype,
dn, attr, value,
&req->id1name,
&req->id1.idmap_id_u.sid.prefix,
&req->id1.idmap_id_u.sid.rid,
- (int *)&req->id2.idtype, unixname,
+ &req->id2.idtype, unixname,
pid,
&res->retcode);
if (retcode == IDMAP_SUCCESS)
num_queued++;
}
- } else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) {
+ } else if (IS_ID_UID(req->id1) || IS_ID_GID(req->id1)) {
/* unix2win request: */
@@ -2038,10 +2072,10 @@ retry:
retcode = idmap_sid2name_batch_add1(
qs, res->id.idmap_id_u.sid.prefix,
&res->id.idmap_id_u.sid.rid,
- _IDMAP_T_UNDEF,
+ IDMAP_POSIXID,
NULL, NULL, NULL,
&req->id2name,
- &req->id2domain, (int *)&req->id2.idtype,
+ &req->id2domain, &req->id2.idtype,
NULL, NULL, &res->retcode);
if (retcode == IDMAP_SUCCESS)
num_queued++;
@@ -2055,11 +2089,11 @@ retry:
*/
retcode = idmap_name2sid_batch_add1(
qs, req->id2name, req->id2domain,
- _IDMAP_T_UNDEF,
+ IDMAP_POSIXID,
NULL, NULL, NULL, NULL,
&res->id.idmap_id_u.sid.prefix,
&res->id.idmap_id_u.sid.rid,
- (int *)&req->id2.idtype, NULL,
+ &req->id2.idtype, NULL,
NULL,
&res->retcode);
if (retcode == IDMAP_SUCCESS)
@@ -2069,7 +2103,7 @@ retry:
(how_local & DOMAIN_IS_LOCAL)) {
assert(req->id1.idmap_id_u.uid !=
IDMAP_SENTINEL_PID);
- is_user = IS_REQUEST_UID(*req);
+ is_user = IS_ID_UID(req->id1);
if (res->id.idtype == IDMAP_USID)
is_wuser = 1;
else if (res->id.idtype == IDMAP_GSID)
@@ -2081,7 +2115,7 @@ retry:
if (is_user != is_wuser)
continue;
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
res->info.src = IDMAP_MAP_SRC_NEW;
how->map_type = IDMAP_MAP_TYPE_IDMU;
retcode = idmap_pid2sid_batch_add1(
@@ -2092,7 +2126,7 @@ retry:
&res->id.idmap_id_u.sid.prefix,
&res->id.idmap_id_u.sid.rid,
&req->id2name, &req->id2domain,
- (int *)&req->id2.idtype, &res->retcode);
+ &req->id2.idtype, &res->retcode);
if (retcode == IDMAP_SUCCESS)
num_queued++;
} else if (req->id1name != NULL) {
@@ -2100,7 +2134,7 @@ retry:
* No SID and no winname but we've unixname.
* Lookup AD by unixname to get SID.
*/
- is_user = (IS_REQUEST_UID(*req)) ? 1 : 0;
+ is_user = (IS_ID_UID(req->id1)) ? 1 : 0;
if (res->id.idtype == IDMAP_USID)
is_wuser = 1;
else if (res->id.idtype == IDMAP_GSID)
@@ -2108,7 +2142,7 @@ retry:
else
is_wuser = is_user;
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
res->info.src = IDMAP_MAP_SRC_NEW;
how->map_type = IDMAP_MAP_TYPE_DS_AD;
retcode = idmap_unixname2sid_batch_add1(
@@ -2119,7 +2153,7 @@ retry:
&res->id.idmap_id_u.sid.prefix,
&res->id.idmap_id_u.sid.rid,
&req->id2name, &req->id2domain,
- (int *)&req->id2.idtype, &res->retcode);
+ &req->id2.idtype, &res->retcode);
if (retcode == IDMAP_SUCCESS)
num_queued++;
}
@@ -2175,7 +2209,7 @@ out:
* and update the idtype in request.
*/
for (i = 0; i < batch->idmap_mapping_batch_len; i++) {
- int type;
+ idmap_id_type type;
uid_t posix_id;
req = &batch->idmap_mapping_batch_val[i];
@@ -2218,15 +2252,15 @@ out:
if (res->retcode == IDMAP_ERR_NOTFOUND) {
/* Nothing found - remove the preset info */
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
}
- if (IS_REQUEST_SID(*req, 1)) {
+ if (IS_ID_SID(req->id1)) {
if (res->retcode != IDMAP_SUCCESS)
continue;
/* Evaluate result type */
switch (type) {
- case _IDMAP_T_USER:
+ case IDMAP_USID:
if (res->id.idtype == IDMAP_POSIXID)
res->id.idtype = IDMAP_UID;
/*
@@ -2245,7 +2279,7 @@ out:
req->id1.idtype = IDMAP_USID;
break;
- case _IDMAP_T_GROUP:
+ case IDMAP_GSID:
if (res->id.idtype == IDMAP_POSIXID)
res->id.idtype = IDMAP_GID;
/*
@@ -2276,7 +2310,7 @@ out:
req->direction |= _IDMAP_F_LOOKUP_NLDAP;
state->nldap_nqueries++;
}
- } else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) {
+ } else if (IS_ID_UID(req->id1) || IS_ID_GID(req->id1)) {
if (res->retcode != IDMAP_SUCCESS) {
if ((!(IDMAP_FATAL_ERROR(res->retcode))) &&
res->id.idmap_id_u.sid.prefix == NULL &&
@@ -2295,14 +2329,10 @@ out:
}
/* Evaluate result type */
switch (type) {
- case _IDMAP_T_USER:
+ case IDMAP_USID:
+ case IDMAP_GSID:
if (res->id.idtype == IDMAP_SID)
- res->id.idtype = IDMAP_USID;
- break;
-
- case _IDMAP_T_GROUP:
- if (res->id.idtype == IDMAP_SID)
- res->id.idtype = IDMAP_GSID;
+ res->id.idtype = type;
break;
default:
@@ -2519,19 +2549,33 @@ sid2pid_first_pass(lookup_state_t *state, idmap_mapping *req,
/* Lookup well-known SIDs table */
retcode = lookup_wksids_sid2pid(req, res, &wksid);
- /*
- * Note that IDMAP_SUCCESS means that we found a hardwired mapping.
- * If we found a well-known identity but no mapping, wksid==true and
- * retcode==IDMAP_ERR_NOTFOUND.
- */
- if (retcode != IDMAP_ERR_NOTFOUND)
+ if (retcode == IDMAP_SUCCESS) {
+ /* Found a well-known account with a hardwired mapping */
+ TRACE(req, res, "Hardwired mapping");
+ goto out;
+ } else if (retcode != IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res,
+ "Well-known account lookup failed, code %d", retcode);
goto out;
+ }
+
+ if (wksid) {
+ /* Found a well-known account, but no mapping */
+ TRACE(req, res, "Well-known account");
+ } else {
+ TRACE(req, res, "Not a well-known account");
- if (!wksid) {
/* Check if this is a localsid */
retcode = lookup_localsid2pid(req, res);
- if (retcode != IDMAP_ERR_NOTFOUND)
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Local SID");
+ goto out;
+ } else if (retcode != IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res,
+ "Local SID lookup error=%d", retcode);
goto out;
+ }
+ TRACE(req, res, "Not a local SID");
if (ALLOW_WK_OR_LOCAL_SIDS_ONLY(req)) {
retcode = IDMAP_ERR_NONE_GENERATED;
@@ -2557,12 +2601,19 @@ sid2pid_first_pass(lookup_state_t *state, idmap_mapping *req,
retcode = IDMAP_ERR_MEMORY;
goto out;
}
+ TRACE(req, res, "Added default domain");
}
/* Lookup cache */
retcode = lookup_cache_sid2pid(state->cache, req, res);
- if (retcode != IDMAP_ERR_NOTFOUND)
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Found in mapping cache");
goto out;
+ } else if (retcode != IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res, "Mapping cache lookup error=%d", retcode);
+ goto out;
+ }
+ TRACE(req, res, "Not found in mapping cache");
if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) {
retcode = IDMAP_ERR_NONE_GENERATED;
@@ -2579,9 +2630,64 @@ sid2pid_first_pass(lookup_state_t *state, idmap_mapping *req,
* batched for AD lookup.
*/
retcode = lookup_name_cache(state->cache, req, res);
- if (retcode != IDMAP_SUCCESS && retcode != IDMAP_ERR_NOTFOUND)
+ if (retcode == IDMAP_SUCCESS) {
+ if (res->id.idtype == IDMAP_POSIXID) {
+ if (req->id1.idtype == IDMAP_USID)
+ res->id.idtype = IDMAP_UID;
+ else
+ res->id.idtype = IDMAP_GID;
+ }
+ } else if (retcode != IDMAP_ERR_NOTFOUND)
goto out;
+ if (_idmapdstate.cfg->pgcfg.use_lsa &&
+ _idmapdstate.cfg->pgcfg.domain_name != NULL) {
+ /*
+ * If we don't have both name and SID, try looking up the
+ * entry with LSA.
+ */
+ if (req->id1.idmap_id_u.sid.prefix != NULL &&
+ req->id1name == NULL) {
+
+ retcode = lookup_lsa_by_sid(
+ req->id1.idmap_id_u.sid.prefix,
+ req->id1.idmap_id_u.sid.rid,
+ &req->id1name, &req->id1domain, &req->id1.idtype);
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Found with LSA");
+ } else if (retcode == IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res, "Not found with LSA");
+ } else {
+ TRACE(req, res, "LSA error %d", retcode);
+ goto out;
+ }
+
+ } else if (req->id1name != NULL &&
+ req->id1.idmap_id_u.sid.prefix == NULL) {
+ char *canonname;
+ char *canondomain;
+
+ retcode = lookup_lsa_by_name(
+ req->id1name, req->id1domain,
+ &req->id1.idmap_id_u.sid.prefix,
+ &req->id1.idmap_id_u.sid.rid,
+ &canonname, &canondomain,
+ &req->id1.idtype);
+ if (retcode == IDMAP_SUCCESS) {
+ free(req->id1name);
+ req->id1name = canonname;
+ free(req->id1domain);
+ req->id1domain = canondomain;
+ TRACE(req, res, "Found with LSA");
+ } else if (retcode == IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res, "Not found with LSA");
+ } else {
+ TRACE(req, res, "LSA error %d", retcode);
+ goto out;
+ }
+ }
+ }
+
/*
* Set the flag to indicate that we are not done yet so that
* subsequent passes considers this request for name-based
@@ -2652,7 +2758,7 @@ generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user,
RDLOCK_CONFIG();
/*
* machine_sid is never NULL because if it is we won't be here.
- * No need to assert because stdrup(NULL) will core anyways.
+ * No need to assert because strdup(NULL) will core anyways.
*/
res->id.idmap_id_u.sid.prefix =
strdup(_idmapdstate.cfg->pgcfg.machine_sid);
@@ -2956,6 +3062,12 @@ name_based_mapping_sid2pid(lookup_state_t *state,
retcode = IDMAP_ERR_INTERNAL;
goto out;
}
+
+ TRACE(req, res, "Matching rule: %s@%s -> %s",
+ values[2] == NULL ? "(null)" : values[2],
+ values[3] == NULL ? "(null)" : values[3],
+ values[0] == NULL ? "(null)" : values[0]);
+
if (values[0] == NULL) {
retcode = IDMAP_ERR_INTERNAL;
goto out;
@@ -2969,6 +3081,7 @@ name_based_mapping_sid2pid(lookup_state_t *state,
direction = IDMAP_DIRECTION_W2U;
if (EMPTY_NAME(values[0])) {
+ TRACE(req, res, "Mapping inhibited");
idmap_namerule_set(rule, values[3], values[2],
values[0], is_user, is_wuser,
strtol(values[4], &end, 10),
@@ -2987,11 +3100,18 @@ name_based_mapping_sid2pid(lookup_state_t *state,
retcode = ns_lookup_byname(unixname, lower_unixname,
&res->id);
- if (retcode == IDMAP_ERR_NOTFOUND) {
- if (values[0][0] == '*')
+ if (retcode == IDMAP_SUCCESS) {
+ break;
+ } else if (retcode == IDMAP_ERR_NOTFOUND) {
+ if (values[0][0] == '*') {
+ TRACE(req, res,
+ "%s not found, continuing",
+ unixname);
/* Case 4 */
continue;
- else {
+ } else {
+ TRACE(req, res,
+ "%s not found, error", unixname);
/* Case 3 */
idmap_namerule_set(rule, values[3],
values[2], values[0], is_user,
@@ -3000,6 +3120,9 @@ name_based_mapping_sid2pid(lookup_state_t *state,
direction);
retcode = IDMAP_ERR_NOMAPPING;
}
+ } else {
+ TRACE(req, res, "Looking up %s error=%d",
+ unixname, retcode);
}
goto out;
} else if (r == SQLITE_DONE) {
@@ -3016,29 +3139,36 @@ name_based_mapping_sid2pid(lookup_state_t *state,
}
}
-out:
- if (sql != NULL)
- sqlite_freemem(sql);
- if (retcode == IDMAP_SUCCESS) {
- if (values[1] != NULL)
- res->direction =
- (strtol(values[1], &end, 10) == 0)?
- IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI;
- else
- res->direction = IDMAP_DIRECTION_W2U;
+ /* Found */
- req->id2name = strdup(unixname);
- if (req->id2name == NULL) {
- retcode = IDMAP_ERR_MEMORY;
- }
+ if (values[1] != NULL)
+ res->direction =
+ (strtol(values[1], &end, 10) == 0)?
+ IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI;
+ else
+ res->direction = IDMAP_DIRECTION_W2U;
+
+ req->id2name = strdup(unixname);
+ if (req->id2name == NULL) {
+ retcode = IDMAP_ERR_MEMORY;
+ goto out;
}
+ TRACE(req, res, "UNIX name found");
- if (retcode == IDMAP_SUCCESS) {
- idmap_namerule_set(rule, values[3], values[2],
- values[0], is_user, is_wuser, strtol(values[4], &end, 10),
- res->direction);
+ idmap_namerule_set(rule, values[3], values[2],
+ values[0], is_user, is_wuser, strtol(values[4], &end, 10),
+ res->direction);
+
+out:
+ if (retcode != IDMAP_SUCCESS &&
+ retcode != IDMAP_ERR_NOTFOUND &&
+ retcode != IDMAP_ERR_NOMAPPING) {
+ TRACE(req, res, "Rule processing error, code=%d", retcode);
}
+ if (sql != NULL)
+ sqlite_freemem(sql);
+
if (retcode != IDMAP_ERR_NOTFOUND) {
res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED;
res->info.src = IDMAP_MAP_SRC_NEW;
@@ -3224,6 +3354,7 @@ sid2pid_second_pass(lookup_state_t *state,
idmap_mapping *req, idmap_id_res *res)
{
idmap_retcode retcode;
+ idmap_retcode retcode2;
/* Check if second pass is needed */
if (ARE_WE_DONE(req->direction))
@@ -3242,8 +3373,14 @@ sid2pid_second_pass(lookup_state_t *state,
*/
if (req->id1.idtype == IDMAP_SID)
req->id1.idtype = IDMAP_USID;
- if (res->id.idtype == IDMAP_POSIXID)
+ if (res->id.idtype == IDMAP_POSIXID) {
res->id.idtype = IDMAP_UID;
+ TRACE(req, res, "Assume unresolvable SID is user");
+ } else if (res->id.idtype == IDMAP_UID) {
+ TRACE(req, res, "Must map unresolvable SID to user");
+ } else if (res->id.idtype == IDMAP_GID) {
+ TRACE(req, res, "Must map unresolvable SID to group");
+ }
goto do_eph;
}
if (retcode != IDMAP_SUCCESS)
@@ -3265,8 +3402,15 @@ sid2pid_second_pass(lookup_state_t *state,
* have a UID or GID that isn't in the
* name service.
*/
- (void) ns_lookup_bypid(res->id.idmap_id_u.uid,
+ retcode2 = ns_lookup_bypid(res->id.idmap_id_u.uid,
res->id.idtype == IDMAP_UID, &req->id2name);
+ if (IDMAP_ERROR(retcode2)) {
+ TRACE(req, res,
+ "Getting UNIX name, error=%d (ignored)",
+ retcode2);
+ } else {
+ TRACE(req, res, "Found UNIX name");
+ }
}
goto out;
}
@@ -3332,42 +3476,65 @@ sid2pid_second_pass(lookup_state_t *state,
res->id.idtype == IDMAP_GID) ||
(req->id1.idtype == IDMAP_GSID &&
res->id.idtype == IDMAP_UID))) {
+ TRACE(req, res, "Ignoring UNIX name found in AD");
free(req->id2name);
req->id2name = NULL;
res->id.idmap_id_u.uid = IDMAP_SENTINEL_PID;
/* fallback */
} else {
- if (res->id.idmap_id_u.uid == IDMAP_SENTINEL_PID)
+ if (res->id.idmap_id_u.uid == IDMAP_SENTINEL_PID) {
retcode = ns_lookup_byname(req->id2name,
NULL, &res->id);
- /*
- * If ns_lookup_byname() fails that means the
- * unixname (req->id2name), which was obtained
- * from the AD object by directory-based mapping,
- * is not a valid Unix user/group and therefore
- * we return the error to the client instead of
- * doing rule-based mapping or ephemeral mapping.
- * This way the client can detect the issue.
- */
+ if (retcode != IDMAP_SUCCESS) {
+ /*
+ * If ns_lookup_byname() fails that
+ * means the unixname (req->id2name),
+ * which was obtained from the AD
+ * object by directory-based mapping,
+ * is not a valid Unix user/group and
+ * therefore we return the error to the
+ * client instead of doing rule-based
+ * mapping or ephemeral mapping. This
+ * way the client can detect the issue.
+ */
+ TRACE(req, res,
+ "UNIX lookup error=%d", retcode);
+ goto out;
+ }
+ TRACE(req, res, "UNIX lookup");
+ }
goto out;
}
}
/* Free any mapping info from Directory based mapping */
if (res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN)
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
/*
* If we don't have unixname then evaluate local name-based
* mapping rules.
*/
retcode = name_based_mapping_sid2pid(state, req, res);
- if (retcode != IDMAP_ERR_NOTFOUND)
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Rule-based mapping");
goto out;
+ } else if (retcode != IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res, "Rule-based mapping error=%d", retcode);
+ goto out;
+ }
+ TRACE(req, res, "No matching rule");
do_eph:
/* If not found, do ephemeral mapping */
retcode = dynamic_ephemeral_mapping(state, req, res);
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Ephemeral mapping");
+ goto out;
+ } else if (retcode != IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res, "Ephemeral mapping error=%d", retcode);
+ goto out;
+ }
out:
res->retcode = idmap_stat4prot(retcode);
@@ -3386,6 +3553,7 @@ update_cache_pid2sid(lookup_state_t *state,
{
char *sql = NULL;
idmap_retcode retcode;
+ idmap_retcode retcode2;
char *map_dn = NULL;
char *map_attr = NULL;
char *map_value = NULL;
@@ -3420,8 +3588,12 @@ update_cache_pid2sid(lookup_state_t *state,
* If we can't find it... c'est la vie.
*/
if (req->id1name == NULL) {
- (void) ns_lookup_bypid(req->id1.idmap_id_u.uid,
+ retcode2 = ns_lookup_bypid(req->id1.idmap_id_u.uid,
req->id1.idtype == IDMAP_UID, &req->id1name);
+ if (retcode2 == IDMAP_SUCCESS)
+ TRACE(req, res, "Found UNIX name");
+ else
+ TRACE(req, res, "Getting UNIX name error=%d", retcode2);
}
assert(res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN);
@@ -3458,7 +3630,7 @@ update_cache_pid2sid(lookup_state_t *state,
break;
default:
- /* Dont cache other mapping types */
+ /* Don't cache other mapping types */
assert(FALSE);
}
@@ -3508,7 +3680,7 @@ update_cache_pid2sid(lookup_state_t *state,
"VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ",
res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid,
req->id2name, req->id2domain,
- (res->id.idtype == IDMAP_USID) ? _IDMAP_T_USER : _IDMAP_T_GROUP);
+ res->id.idtype);
if (sql == NULL) {
retcode = IDMAP_ERR_INTERNAL;
@@ -3519,8 +3691,6 @@ update_cache_pid2sid(lookup_state_t *state,
retcode = sql_exec_no_cb(state->cache, IDMAP_CACHENAME, sql);
out:
- if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO))
- idmap_info_free(&res->info);
if (sql != NULL)
sqlite_freemem(sql);
return (retcode);
@@ -3612,7 +3782,7 @@ update_cache_sid2pid(lookup_state_t *state,
break;
default:
- /* Dont cache other mapping types */
+ /* Don't cache other mapping types */
assert(FALSE);
}
@@ -3659,7 +3829,7 @@ update_cache_sid2pid(lookup_state_t *state,
"VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ",
req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid,
req->id1name, req->id1domain,
- (req->id1.idtype == IDMAP_USID) ? _IDMAP_T_USER : _IDMAP_T_GROUP);
+ req->id1.idtype);
if (sql == NULL) {
retcode = IDMAP_ERR_INTERNAL;
@@ -3670,9 +3840,6 @@ update_cache_sid2pid(lookup_state_t *state,
retcode = sql_exec_no_cb(state->cache, IDMAP_CACHENAME, sql);
out:
- if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO))
- idmap_info_free(&res->info);
-
if (sql != NULL)
sqlite_freemem(sql);
return (retcode);
@@ -3889,8 +4056,14 @@ out:
*/
static
idmap_retcode
-lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain,
- char **canonname, char **sidprefix, idmap_rid_t *rid, int *type)
+lookup_cache_name2sid(
+ sqlite *cache,
+ const char *name,
+ const char *domain,
+ char **canonname,
+ char **sidprefix,
+ idmap_rid_t *rid,
+ idmap_id_type *type)
{
char *end, *lower_name;
char *sql;
@@ -3939,7 +4112,7 @@ lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain,
retcode = IDMAP_ERR_CACHE;
goto out;
}
- *type = strtol(values[2], &end, 10);
+ *type = xlate_legacy_type(strtol(values[2], &end, 10));
}
if (values[0] == NULL || values[1] == NULL) {
@@ -3985,9 +4158,9 @@ out:
static
idmap_retcode
ad_lookup_by_winname(lookup_state_t *state,
- const char *name, const char *domain, int eunixtype,
+ const char *name, const char *domain, int esidtype,
char **dn, char **attr, char **value, char **canonname,
- char **sidprefix, idmap_rid_t *rid, int *wintype,
+ char **sidprefix, idmap_rid_t *rid, idmap_id_type *wintype,
char **unixname)
{
int retries;
@@ -4034,7 +4207,7 @@ retry:
}
retcode = idmap_name2sid_batch_add1(qs, name, domain,
- eunixtype, dn, attr, value, canonname, sidprefix,
+ esidtype, dn, attr, value, canonname, sidprefix,
rid, wintype, unixname, NULL, &rc);
if (retcode == IDMAP_ERR_DOMAIN_NOTFOUND) {
idmap_lookup_release_batch(&qs);
@@ -4092,15 +4265,15 @@ lookup_name2sid(
sqlite *cache,
const char *name,
const char *domain,
- int *is_wuser,
+ int want_wuser,
char **canonname,
char **canondomain,
char **sidprefix,
idmap_rid_t *rid,
+ idmap_id_type *type,
idmap_mapping *req,
int local_only)
{
- int type;
idmap_retcode retcode;
*sidprefix = NULL;
@@ -4111,7 +4284,7 @@ lookup_name2sid(
/* Lookup well-known SIDs table */
retcode = lookup_wksids_name2sid(name, domain, canonname, canondomain,
- sidprefix, rid, &type);
+ sidprefix, rid, type);
if (retcode == IDMAP_SUCCESS) {
req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE;
goto out;
@@ -4121,7 +4294,7 @@ lookup_name2sid(
/* Lookup cache */
retcode = lookup_cache_name2sid(cache, name, domain, canonname,
- sidprefix, rid, &type);
+ sidprefix, rid, type);
if (retcode == IDMAP_SUCCESS) {
req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE;
goto out;
@@ -4138,28 +4311,39 @@ lookup_name2sid(
if (local_only)
return (retcode);
+ if (_idmapdstate.cfg->pgcfg.use_lsa &&
+ _idmapdstate.cfg->pgcfg.domain_name != NULL &&
+ name != NULL && *sidprefix == NULL) {
+ retcode = lookup_lsa_by_name(name, domain,
+ sidprefix, rid,
+ canonname, canondomain,
+ type);
+ if (retcode == IDMAP_SUCCESS)
+ goto out;
+ else if (retcode != IDMAP_ERR_NOTFOUND)
+ return (retcode);
+ }
+
/* Lookup AD */
- retcode = ad_lookup_by_winname(NULL, name, domain, _IDMAP_T_UNDEF,
- NULL, NULL, NULL, canonname, sidprefix, rid, &type, NULL);
+ retcode = ad_lookup_by_winname(NULL, name, domain, IDMAP_POSIXID,
+ NULL, NULL, NULL, canonname, sidprefix, rid, type, NULL);
if (retcode != IDMAP_SUCCESS)
return (retcode);
out:
/*
* Entry found (cache or Windows lookup)
- * is_wuser is both input as well as output parameter
*/
- if (*is_wuser == 1 && type != _IDMAP_T_USER)
+ if (want_wuser == 1 && *type != IDMAP_USID)
retcode = IDMAP_ERR_NOTUSER;
- else if (*is_wuser == 0 && type != _IDMAP_T_GROUP)
+ else if (want_wuser == 0 && *type != IDMAP_GSID)
retcode = IDMAP_ERR_NOTGROUP;
- else if (*is_wuser == -1) {
- /* Caller wants to know if its user or group */
- if (type == _IDMAP_T_USER)
- *is_wuser = 1;
- else if (type == _IDMAP_T_GROUP)
- *is_wuser = 0;
- else
+ else if (want_wuser == -1) {
+ /*
+ * Caller wants to know if its user or group
+ * Verify that it's one or the other.
+ */
+ if (*type != IDMAP_USID && *type != IDMAP_GSID)
retcode = IDMAP_ERR_SID;
}
@@ -4204,7 +4388,7 @@ name_based_mapping_pid2sid(lookup_state_t *state, const char *unixname,
const char **values;
sqlite_vm *vm = NULL;
int ncol, r;
- int is_wuser;
+ int want_wuser;
const char *me = "name_based_mapping_pid2sid";
int non_wild_match = FALSE;
idmap_namerule *rule = &res->info.how.idmap_how_u.rule;
@@ -4243,6 +4427,12 @@ name_based_mapping_pid2sid(lookup_state_t *state, const char *unixname,
retcode = IDMAP_ERR_INTERNAL;
goto out;
}
+
+ TRACE(req, res, "Matching rule: %s -> %s@%s",
+ values[4] == NULL ? "(null)" : values[4],
+ values[0] == NULL ? "(null)" : values[0],
+ values[1] == NULL ? "(null)" : values[1]);
+
if (values[0] == NULL) {
/* values [1] and [2] can be null */
retcode = IDMAP_ERR_INTERNAL;
@@ -4262,6 +4452,7 @@ name_based_mapping_pid2sid(lookup_state_t *state, const char *unixname,
strtol(values[3], &end, 10),
strtol(values[5], &end, 10),
direction);
+ TRACE(req, res, "Mapping inhibited");
retcode = IDMAP_ERR_NOMAPPING;
goto out;
}
@@ -4290,28 +4481,44 @@ name_based_mapping_pid2sid(lookup_state_t *state, const char *unixname,
}
winname = values[0];
}
- is_wuser = res->id.idtype == IDMAP_USID ? 1
+ want_wuser = res->id.idtype == IDMAP_USID ? 1
: res->id.idtype == IDMAP_GSID ? 0
: -1;
if (values[1] != NULL)
windomain = values[1];
- else if (state->defdom != NULL)
+ else if (state->defdom != NULL) {
windomain = state->defdom;
- else {
+ TRACE(req, res,
+ "Added default domain %s to rule",
+ windomain);
+ } else {
idmapdlog(LOG_ERR, "%s: no domain", me);
+ TRACE(req, res,
+ "No domain in rule, and no default domain");
retcode = IDMAP_ERR_DOMAIN_NOTFOUND;
goto out;
}
retcode = lookup_name2sid(state->cache,
winname, windomain,
- &is_wuser, &canonname, &canondomain,
+ want_wuser, &canonname, &canondomain,
&res->id.idmap_id_u.sid.prefix,
- &res->id.idmap_id_u.sid.rid, req, 0);
+ &res->id.idmap_id_u.sid.rid,
+ &res->id.idtype, req, 0);
- if (retcode == IDMAP_ERR_NOTFOUND) {
+ if (retcode == IDMAP_SUCCESS) {
+ break;
+ } else if (retcode == IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res,
+ "%s@%s not found, continuing",
+ winname, windomain);
continue;
+ } else {
+ TRACE(req, res,
+ "Looking up %s@%s error=%d",
+ winname, windomain, retcode);
}
+
goto out;
} else if (r == SQLITE_DONE) {
@@ -4336,29 +4543,25 @@ name_based_mapping_pid2sid(lookup_state_t *state, const char *unixname,
}
}
-out:
- if (sql != NULL)
- sqlite_freemem(sql);
- if (retcode == IDMAP_SUCCESS) {
- res->id.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID;
+ if (values[2] != NULL)
+ res->direction =
+ (strtol(values[2], &end, 10) == 0)?
+ IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI;
+ else
+ res->direction = IDMAP_DIRECTION_U2W;
- if (values[2] != NULL)
- res->direction =
- (strtol(values[2], &end, 10) == 0)?
- IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI;
- else
- res->direction = IDMAP_DIRECTION_U2W;
+ req->id2name = canonname;
+ req->id2domain = canondomain;
- req->id2name = canonname;
- req->id2domain = canondomain;
- }
+ idmap_namerule_set(rule, values[1], values[0], values[4],
+ is_user, strtol(values[3], &end, 10),
+ strtol(values[5], &end, 10),
+ rule->direction);
+ TRACE(req, res, "Windows name found");
- if (retcode == IDMAP_SUCCESS) {
- idmap_namerule_set(rule, values[1], values[0], values[4],
- is_user, strtol(values[3], &end, 10),
- strtol(values[5], &end, 10),
- rule->direction);
- }
+out:
+ if (sql != NULL)
+ sqlite_freemem(sql);
if (retcode != IDMAP_ERR_NOTFOUND) {
res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED;
@@ -4432,6 +4635,7 @@ pid2sid_first_pass(lookup_state_t *state, idmap_mapping *req,
idmap_id_res *res, int is_user)
{
idmap_retcode retcode;
+ idmap_retcode retcode2;
bool_t gen_localsid_on_err = FALSE;
/* Initialize result */
@@ -4451,26 +4655,42 @@ pid2sid_first_pass(lookup_state_t *state, idmap_mapping *req,
goto out;
}
- if (ns_lookup_byname(req->id1name, NULL, &req->id1)
- != IDMAP_SUCCESS) {
+ retcode = ns_lookup_byname(req->id1name, NULL, &req->id1);
+ if (retcode != IDMAP_SUCCESS) {
+ TRACE(req, res, "Getting UNIX ID error=%d", retcode);
retcode = IDMAP_ERR_NOMAPPING;
goto out;
}
+ TRACE(req, res, "Found UNIX ID");
}
/* Lookup in well-known SIDs table */
retcode = lookup_wksids_pid2sid(req, res, is_user);
- if (retcode != IDMAP_ERR_NOTFOUND)
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Hardwired mapping");
+ goto out;
+ } else if (retcode != IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res,
+ "Well-known account lookup error=%d", retcode);
goto out;
+ }
/* Lookup in cache */
retcode = lookup_cache_pid2sid(state->cache, req, res, is_user);
- if (retcode != IDMAP_ERR_NOTFOUND)
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Found in mapping cache");
+ goto out;
+ } else if (retcode != IDMAP_ERR_NOTFOUND) {
+ TRACE(req, res,
+ "Mapping cache lookup error=%d", retcode);
goto out;
+ }
+ TRACE(req, res, "Not found in mapping cache");
/* Ephemeral ids cannot be allocated during pid2sid */
if (IDMAP_ID_IS_EPHEMERAL(req->id1.idmap_id_u.uid)) {
retcode = IDMAP_ERR_NOMAPPING;
+ TRACE(req, res, "Shouldn't have an ephemeral ID here");
goto out;
}
@@ -4500,9 +4720,12 @@ pid2sid_first_pass(lookup_state_t *state, idmap_mapping *req,
retcode = ns_lookup_bypid(req->id1.idmap_id_u.uid,
is_user, &req->id1name);
if (retcode != IDMAP_SUCCESS) {
+ TRACE(req, res,
+ "Getting UNIX name error=%d", retcode);
gen_localsid_on_err = TRUE;
goto out;
}
+ TRACE(req, res, "Found UNIX name");
}
req->direction |= _IDMAP_F_LOOKUP_AD;
state->ad_nqueries++;
@@ -4526,9 +4749,16 @@ pid2sid_first_pass(lookup_state_t *state, idmap_mapping *req,
out:
res->retcode = idmap_stat4prot(retcode);
- if (ARE_WE_DONE(req->direction) && res->retcode != IDMAP_SUCCESS)
- if (gen_localsid_on_err == TRUE)
- (void) generate_localsid(req, res, is_user, TRUE);
+ if (ARE_WE_DONE(req->direction) && res->retcode != IDMAP_SUCCESS) {
+ if (gen_localsid_on_err == TRUE) {
+ retcode2 = generate_localsid(req, res, is_user, TRUE);
+ if (retcode2 == IDMAP_SUCCESS)
+ TRACE(req, res, "Generate local SID");
+ else
+ TRACE(req, res,
+ "Generate local SID error=%d", retcode2);
+ }
+ }
return (retcode);
}
@@ -4538,6 +4768,7 @@ pid2sid_second_pass(lookup_state_t *state, idmap_mapping *req,
{
bool_t gen_localsid_on_err = TRUE;
idmap_retcode retcode = IDMAP_SUCCESS;
+ idmap_retcode retcode2;
/* Check if second pass is needed */
if (ARE_WE_DONE(req->direction))
@@ -4561,6 +4792,7 @@ pid2sid_second_pass(lookup_state_t *state, idmap_mapping *req,
if (req->id2name != NULL) {
/* Return notfound if we've winname but no SID. */
if (res->id.idmap_id_u.sid.prefix == NULL) {
+ TRACE(req, res, "Windows name but no SID");
retcode = IDMAP_ERR_NOTFOUND;
goto out;
}
@@ -4583,21 +4815,28 @@ pid2sid_second_pass(lookup_state_t *state, idmap_mapping *req,
/* Free any mapping info from Directory based mapping */
if (res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN)
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
if (req->id1name == NULL) {
/* Get unixname from name service */
retcode = ns_lookup_bypid(req->id1.idmap_id_u.uid, is_user,
&req->id1name);
- if (retcode != IDMAP_SUCCESS)
+ if (retcode != IDMAP_SUCCESS) {
+ TRACE(req, res,
+ "Getting UNIX name error=%d", retcode);
goto out;
+ }
+ TRACE(req, res, "Found UNIX name");
} else if (req->id1.idmap_id_u.uid == IDMAP_SENTINEL_PID) {
/* Get pid from name service */
retcode = ns_lookup_byname(req->id1name, NULL, &req->id1);
if (retcode != IDMAP_SUCCESS) {
+ TRACE(req, res,
+ "Getting UNIX ID error=%d", retcode);
gen_localsid_on_err = FALSE;
goto out;
}
+ TRACE(req, res, "Found UNIX ID");
}
/* Use unixname to evaluate local name-based mapping rules */
@@ -4605,6 +4844,12 @@ pid2sid_second_pass(lookup_state_t *state, idmap_mapping *req,
req, res);
if (retcode == IDMAP_ERR_NOTFOUND) {
retcode = generate_localsid(req, res, is_user, FALSE);
+ if (retcode == IDMAP_SUCCESS) {
+ TRACE(req, res, "Generated local SID");
+ } else {
+ TRACE(req, res,
+ "Generating local SID error=%d", retcode);
+ }
gen_localsid_on_err = FALSE;
}
@@ -4616,10 +4861,16 @@ out:
req->id2name = NULL;
free(req->id2domain);
req->id2domain = NULL;
- if (gen_localsid_on_err == TRUE)
- (void) generate_localsid(req, res, is_user, TRUE);
- else
+ if (gen_localsid_on_err == TRUE) {
+ retcode2 = generate_localsid(req, res, is_user, TRUE);
+ if (retcode2 == IDMAP_SUCCESS)
+ TRACE(req, res, "Generate local SID");
+ else
+ TRACE(req, res,
+ "Generate local SID error=%d", retcode2);
+ } else {
res->id.idtype = is_user ? IDMAP_USID : IDMAP_GSID;
+ }
}
if (!ARE_WE_DONE(req->direction))
state->pid2sid_done = FALSE;
diff --git a/usr/src/cmd/idmap/idmapd/idmap.xml b/usr/src/cmd/idmap/idmapd/idmap.xml
index b7400cc811..87933b5507 100644
--- a/usr/src/cmd/idmap/idmapd/idmap.xml
+++ b/usr/src/cmd/idmap/idmapd/idmap.xml
@@ -1,8 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
- Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
CDDL HEADER START
@@ -23,8 +22,6 @@
CDDL HEADER END
- ident "%Z%%M% %I% %E% SMI"
-
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
@@ -101,6 +98,20 @@
value='solaris.smf.value.idmap' />
</property_group>
+ <property_group name='debug' type='application' >
+ <stability value='Unstable' />
+ <propval name='all' type='integer' value='0' />
+ <propval name='config' type='integer' value='0' />
+ <propval name='mapping' type='integer' value='0' />
+ <propval name='discovery' type='integer' value='0' />
+ <propval name='dns' type='integer' value='0' />
+ <propval name='ldap' type='integer' value='0' />
+ <propval
+ name='value_authorization'
+ type='astring'
+ value='solaris.smf.value.idmap' />
+ </property_group>
+
<stability value='Unstable' />
<template>
diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.c b/usr/src/cmd/idmap/idmapd/idmap_config.c
index c25f6da2fc..cf5848aa0f 100644
--- a/usr/src/cmd/idmap/idmapd/idmap_config.c
+++ b/usr/src/cmd/idmap/idmapd/idmap_config.c
@@ -40,12 +40,13 @@
#include <port.h>
#include <net/route.h>
#include <sys/u8_textprep.h>
+#include <note.h>
#include "addisc.h"
#define MACHINE_SID_LEN (9 + 3 * 11)
#define FMRI_BASE "svc:/system/idmap"
#define CONFIG_PG "config"
-#define GENERAL_PG "general"
+#define DEBUG_PG "debug"
#define RECONFIGURE 1
#define POKE_AUTO_DISCOVERY 2
@@ -57,7 +58,6 @@ enum event_type {
EVENT_REFRESH, /* SMF refresh */
};
-/*LINTLIBRARY*/
static pthread_t update_thread_handle = 0;
@@ -72,6 +72,13 @@ struct enum_lookup_map directory_mapping_map[] = {
{ 0, NULL },
};
+struct enum_lookup_map trust_dir_map[] = {
+ { 1, "they trust us" },
+ { 2, "we trust them" },
+ { 3, "we trust each other" },
+ { 0, NULL },
+};
+
static int
generate_machine_sid(char **machine_sid)
{
@@ -125,7 +132,6 @@ prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
{
scf_property_t *scf_prop;
- scf_value_t *value;
*exists = B_FALSE;
@@ -135,6 +141,77 @@ prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
scf_strerror(scf_error()));
return (-1);
}
+
+ if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
+ *exists = B_TRUE;
+
+ scf_property_destroy(scf_prop);
+
+ return (0);
+}
+
+static int
+get_debug(idmap_cfg_handles_t *handles, const char *name)
+{
+ int64_t i64 = 0;
+
+ scf_property_t *scf_prop;
+ scf_value_t *value;
+
+ scf_prop = scf_property_create(handles->main);
+ if (scf_prop == NULL) {
+ idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
+ scf_strerror(scf_error()));
+ abort();
+ }
+ value = scf_value_create(handles->main);
+ if (value == NULL) {
+ idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
+ scf_strerror(scf_error()));
+ abort();
+ }
+
+ if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) {
+ /* this is OK: the property is just undefined */
+ goto destruction;
+ }
+
+
+ if (scf_property_get_value(scf_prop, value) < 0) {
+ /* It is still OK when a property doesn't have any value */
+ goto destruction;
+ }
+
+ if (scf_value_get_integer(value, &i64) != 0) {
+ idmapdlog(LOG_ERR, "Can not retrieve %s/%s: %s",
+ DEBUG_PG, name, scf_strerror(scf_error()));
+ abort();
+ }
+
+destruction:
+ scf_value_destroy(value);
+ scf_property_destroy(scf_prop);
+
+ return ((int)i64);
+}
+
+static int
+get_val_bool(idmap_cfg_handles_t *handles, const char *name,
+ boolean_t *val, boolean_t default_val)
+{
+ int rc = 0;
+
+ scf_property_t *scf_prop;
+ scf_value_t *value;
+
+ *val = default_val;
+
+ scf_prop = scf_property_create(handles->main);
+ if (scf_prop == NULL) {
+ idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
+ scf_strerror(scf_error()));
+ return (-1);
+ }
value = scf_value_create(handles->main);
if (value == NULL) {
idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
@@ -143,16 +220,28 @@ prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
return (-1);
}
- if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
- *exists = B_TRUE;
+ /* It is OK if the property is undefined */
+ if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
+ goto destruction;
+
+
+ /* It is still OK when a property doesn't have any value */
+ if (scf_property_get_value(scf_prop, value) < 0)
+ goto destruction;
+
+ uint8_t b;
+ rc = scf_value_get_boolean(value, &b);
+ if (rc == 0)
+ *val = (boolean_t)b;
+
+destruction:
scf_value_destroy(value);
scf_property_destroy(scf_prop);
- return (0);
+ return (rc);
}
-/* Check if in the case of failure the original value of *val is preserved */
static int
get_val_int(idmap_cfg_handles_t *handles, const char *name,
void *val, scf_type_t type)
@@ -161,12 +250,8 @@ get_val_int(idmap_cfg_handles_t *handles, const char *name,
scf_property_t *scf_prop;
scf_value_t *value;
- uint8_t b;
switch (type) {
- case SCF_TYPE_BOOLEAN:
- *(boolean_t *)val = B_FALSE;
- break;
case SCF_TYPE_COUNT:
*(uint64_t *)val = 0;
break;
@@ -203,10 +288,6 @@ get_val_int(idmap_cfg_handles_t *handles, const char *name,
goto destruction;
switch (type) {
- case SCF_TYPE_BOOLEAN:
- rc = scf_value_get_boolean(value, &b);
- *(boolean_t *)val = b;
- break;
case SCF_TYPE_COUNT:
rc = scf_value_get_count(value, val);
break;
@@ -426,7 +507,10 @@ destruction:
static int
-del_val(idmap_cfg_handles_t *handles, const char *name)
+del_val(
+ idmap_cfg_handles_t *handles,
+ scf_propertygroup_t *pg,
+ const char *name)
{
int rc = -1;
int ret;
@@ -447,13 +531,13 @@ del_val(idmap_cfg_handles_t *handles, const char *name)
}
do {
- if (scf_pg_update(handles->config_pg) == -1) {
+ if (scf_pg_update(pg) == -1) {
idmapdlog(LOG_ERR,
"scf_pg_update(%s) failed: %s",
name, scf_strerror(scf_error()));
goto destruction;
}
- if (scf_transaction_start(tx, handles->config_pg) != 0) {
+ if (scf_transaction_start(tx, pg) != 0) {
idmapdlog(LOG_ERR,
"scf_transaction_start(%s) failed: %s",
name, scf_strerror(scf_error()));
@@ -496,18 +580,19 @@ destruction:
static int
-set_val_astring(idmap_cfg_handles_t *handles, const char *name, const char *val)
+set_val(
+ idmap_cfg_handles_t *handles,
+ scf_propertygroup_t *pg,
+ const char *name,
+ scf_value_t *value)
{
int rc = -1;
- int ret = -2;
int i;
- scf_property_t *scf_prop = NULL;
- scf_value_t *value = NULL;
+ scf_property_t *prop = NULL;
scf_transaction_t *tx = NULL;
scf_transaction_entry_t *ent = NULL;
- if ((scf_prop = scf_property_create(handles->main)) == NULL ||
- (value = scf_value_create(handles->main)) == NULL ||
+ if ((prop = scf_property_create(handles->main)) == NULL ||
(tx = scf_transaction_create(handles->main)) == NULL ||
(ent = scf_entry_create(handles->main)) == NULL) {
idmapdlog(LOG_ERR, "Unable to set property %s",
@@ -515,26 +600,45 @@ set_val_astring(idmap_cfg_handles_t *handles, const char *name, const char *val)
goto destruction;
}
- for (i = 0; i < MAX_TRIES && (ret == -2 || ret == 0); i++) {
- if (scf_transaction_start(tx, handles->config_pg) == -1) {
+ for (i = 0; i < MAX_TRIES; i++) {
+ int ret;
+
+ if (scf_pg_update(pg) == -1) {
idmapdlog(LOG_ERR,
- "scf_transaction_start(%s) failed: %s",
- name, scf_strerror(scf_error()));
+ "scf_pg_update() failed: %s",
+ scf_strerror(scf_error()));
goto destruction;
}
- if (scf_transaction_property_new(tx, ent, name,
- SCF_TYPE_ASTRING) < 0) {
+ if (scf_transaction_start(tx, pg) == -1) {
idmapdlog(LOG_ERR,
- "scf_transaction_property_new() failed: %s",
- scf_strerror(scf_error()));
+ "scf_transaction_start(%s) failed: %s",
+ name, scf_strerror(scf_error()));
goto destruction;
}
- if (scf_value_set_astring(value, val) == -1) {
+ ret = scf_pg_get_property(pg, name, prop);
+ if (ret == SCF_SUCCESS) {
+ if (scf_transaction_property_change_type(tx, ent, name,
+ scf_value_type(value)) < 0) {
+ idmapdlog(LOG_ERR,
+ "scf_transaction_property_change_type(%s)"
+ " failed: %s",
+ name, scf_strerror(scf_error()));
+ goto destruction;
+ }
+ } else if (scf_error() == SCF_ERROR_NOT_FOUND) {
+ if (scf_transaction_property_new(tx, ent, name,
+ scf_value_type(value)) < 0) {
+ idmapdlog(LOG_ERR,
+ "scf_transaction_property_new() failed: %s",
+ scf_strerror(scf_error()));
+ goto destruction;
+ }
+ } else {
idmapdlog(LOG_ERR,
- "scf_value_set_astring() failed: %s",
- scf_strerror(scf_error()));
+ "scf_pg_get_property(%s) failed: %s",
+ name, scf_strerror(scf_error()));
goto destruction;
}
@@ -545,41 +649,90 @@ set_val_astring(idmap_cfg_handles_t *handles, const char *name, const char *val)
goto destruction;
}
- if ((ret = scf_transaction_commit(tx)) == 1)
- break;
-
- if (ret == 0 && i < MAX_TRIES - 1) {
+ ret = scf_transaction_commit(tx);
+ if (ret == 0) {
/*
* Property group set in scf_transaction_start()
* is not the most recent. Update pg, reset tx and
* retry tx.
*/
idmapdlog(LOG_WARNING,
- "scf_transaction_commit(%s) failed - Retry: %s",
+ "scf_transaction_commit(%s) failed: %s",
name, scf_strerror(scf_error()));
- if (scf_pg_update(handles->config_pg) == -1) {
- idmapdlog(LOG_ERR,
- "scf_pg_update() failed: %s",
- scf_strerror(scf_error()));
- goto destruction;
- }
scf_transaction_reset(tx);
+ continue;
+ }
+ if (ret != 1) {
+ idmapdlog(LOG_ERR,
+ "scf_transaction_commit(%s) failed: %s",
+ name, scf_strerror(scf_error()));
+ goto destruction;
}
+ /* Success! */
+ rc = 0;
+ break;
}
+destruction:
+ scf_entry_destroy(ent);
+ scf_transaction_destroy(tx);
+ scf_property_destroy(prop);
+ return (rc);
+}
- if (ret == 1)
- rc = 0;
- else if (ret != -2)
- idmapdlog(LOG_ERR,
- "scf_transaction_commit(%s) failed: %s",
+static int
+set_val_integer(
+ idmap_cfg_handles_t *handles,
+ scf_propertygroup_t *pg,
+ const char *name,
+ int64_t val)
+{
+ scf_value_t *value = NULL;
+ int rc;
+
+ if ((value = scf_value_create(handles->main)) == NULL) {
+ idmapdlog(LOG_ERR, "Unable to set property %s",
name, scf_strerror(scf_error()));
+ return (-1);
+ }
+
+ scf_value_set_integer(value, val);
+
+ rc = set_val(handles, pg, name, value);
-destruction:
scf_value_destroy(value);
- scf_entry_destroy(ent);
- scf_transaction_destroy(tx);
- scf_property_destroy(scf_prop);
+
+ return (rc);
+}
+
+
+static int
+set_val_astring(
+ idmap_cfg_handles_t *handles,
+ scf_propertygroup_t *pg,
+ const char *name,
+ const char *val)
+{
+ scf_value_t *value = NULL;
+ int rc = -1;
+
+ if ((value = scf_value_create(handles->main)) == NULL) {
+ idmapdlog(LOG_ERR, "Unable to set property %s",
+ name, scf_strerror(scf_error()));
+ goto out;
+ }
+
+ if (scf_value_set_astring(value, val) == -1) {
+ idmapdlog(LOG_ERR,
+ "scf_value_set_astring() failed: %s",
+ scf_strerror(scf_error()));
+ goto out;
+ }
+
+ rc = set_val(handles, pg, name, value);
+
+out:
+ scf_value_destroy(value);
return (rc);
}
@@ -595,12 +748,15 @@ update_bool(boolean_t *value, boolean_t *new, char *name)
if (*value == *new)
return (0);
- idmapdlog(LOG_INFO, "change %s=%s", name, *new ? "true" : "false");
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_INFO, "change %s=%s", name,
+ *new ? "true" : "false");
+ }
+
*value = *new;
return (1);
}
-
/*
* This function updates a string value.
* If nothing has changed it returns 0 else 1
@@ -608,21 +764,29 @@ update_bool(boolean_t *value, boolean_t *new, char *name)
static int
update_string(char **value, char **new, char *name)
{
- if (*new == NULL)
- return (0);
+ int changed;
+
+ if (*new == NULL && *value != NULL)
+ changed = 1;
+ else if (*new != NULL && *value == NULL)
+ changed = 1;
+ else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0)
+ changed = 1;
+ else
+ changed = 0;
- if (*value != NULL && strcmp(*new, *value) == 0) {
- free(*new);
- *new = NULL;
- return (0);
- }
+ /*
+ * Note that even if unchanged we can't just return; we must free one
+ * of the values.
+ */
- idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
- if (*value != NULL)
- free(*value);
+ if (DBG(CONFIG, 1) && changed)
+ idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
+
+ free(*value);
*value = *new;
*new = NULL;
- return (1);
+ return (changed);
}
static int
@@ -631,7 +795,10 @@ update_enum(int *value, int *new, char *name, struct enum_lookup_map *map)
if (*value == *new)
return (0);
- idmapdlog(LOG_INFO, "change %s=%s", name, enum_lookup(*new, map));
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_INFO, "change %s=%s", name,
+ enum_lookup(*new, map));
+ }
*value = *new;
@@ -666,14 +833,18 @@ update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
if (*value == NULL) {
/* We're unsetting this DS property */
- idmapdlog(LOG_INFO, "change %s=<none>", name);
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_INFO, "change %s=<none>", name);
return (1);
}
- /* List all the new DSs */
- for (i = 0; (*value)[i].host[0] != '\0'; i++)
- idmapdlog(LOG_INFO, "change %s=%s port=%d", name,
- (*value)[i].host, (*value)[i].port);
+ if (DBG(CONFIG, 1)) {
+ /* List all the new DSs */
+ for (i = 0; (*value)[i].host[0] != '\0'; i++) {
+ idmapdlog(LOG_INFO, "change %s=%s port=%d", name,
+ (*value)[i].host, (*value)[i].port);
+ }
+ }
return (1);
}
@@ -706,15 +877,19 @@ update_trusted_domains(ad_disc_trusteddomains_t **value,
if (*value == NULL) {
/* We're unsetting this DS property */
- idmapdlog(LOG_INFO, "change %s=<none>", name);
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_INFO, "change %s=<none>", name);
return (1);
}
- /* List all the new domains */
- for (i = 0; (*value)[i].domain[0] != '\0'; i++)
- idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
- (*value)[i].domain,
- (*value)[i].direction == 3 ? "bi-directional" : "inbound");
+ if (DBG(CONFIG, 1)) {
+ /* List all the new domains */
+ for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
+ idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
+ (*value)[i].domain,
+ enum_lookup((*value)[i].direction, trust_dir_map));
+ }
+ }
return (1);
}
@@ -748,14 +923,18 @@ update_domains_in_forest(ad_disc_domainsinforest_t **value,
if (*value == NULL) {
/* We're unsetting this DS property */
- idmapdlog(LOG_INFO, "change %s=<none>", name);
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_INFO, "change %s=<none>", name);
return (1);
}
- /* List all the new domains */
- for (i = 0; (*value)[i].domain[0] != '\0'; i++)
- idmapdlog(LOG_INFO, "change %s=%s", name,
- (*value)[i].domain);
+ if (DBG(CONFIG, 1)) {
+ /* List all the new domains */
+ for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
+ idmapdlog(LOG_INFO, "change %s=%s", name,
+ (*value)[i].domain);
+ }
+ }
return (1);
}
@@ -865,26 +1044,36 @@ not_equal:
if (*value == NULL) {
/* We're unsetting this DS property */
- idmapdlog(LOG_INFO, "change %s=<none>", name);
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_INFO, "change %s=<none>", name);
return (1);
}
- /* List all the trusted forests */
- for (i = 0; i < *num_value; i++) {
- for (j = 0; (*value)[i].domains_in_forest[j].domain[0] != '\0';
- j++) {
- /* List trusted Domains in the forest. */
- if ((*value)[i].domains_in_forest[j].trusted)
- idmapdlog(LOG_INFO, "change %s=%s domain=%s",
- name, (*value)[i].forest_name,
- (*value)[i].domains_in_forest[j].domain);
+ if (DBG(CONFIG, 1)) {
+ /* List all the trusted forests */
+ for (i = 0; i < *num_value; i++) {
+ idmap_trustedforest_t *f = &(*value)[i];
+ for (j = 0;
+ f->domains_in_forest[j].domain[0] != '\0';
+ j++) {
+ /* List trusted Domains in the forest. */
+ if (f->domains_in_forest[j].trusted)
+ idmapdlog(LOG_INFO,
+ "change %s=%s domain=%s",
+ name, f->forest_name,
+ f->domains_in_forest[j].domain);
+ }
+ /* List the hosts */
+ for (j = 0;
+ f->global_catalog[j].host[0] != '\0';
+ j++) {
+ idmapdlog(LOG_INFO,
+ "change %s=%s host=%s port=%d",
+ name, f->forest_name,
+ f->global_catalog[j].host,
+ f->global_catalog[j].port);
+ }
}
- /* List the hosts */
- for (j = 0; (*value)[i].global_catalog[j].host[0] != '\0'; j++)
- idmapdlog(LOG_INFO, "change %s=%s host=%s port=%d",
- name, (*value)[i].forest_name,
- (*value)[i].global_catalog[j].host,
- (*value)[i].global_catalog[j].port);
}
return (1);
}
@@ -950,7 +1139,7 @@ wait_for_event(struct timespec *timeoutp)
{
port_event_t pe;
- memset(&pe, 0, sizeof (pe));
+ (void) memset(&pe, 0, sizeof (pe));
if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
switch (errno) {
case EINTR:
@@ -1004,12 +1193,16 @@ wait_for_event(struct timespec *timeoutp)
* timeout if need be.
*/
if (pfroute_event_is_interesting(rt_sock)) {
- idmapdlog(LOG_DEBUG,
- "Interesting routing event");
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_DEBUG,
+ "Interesting routing event");
+ }
return (EVENT_ROUTING);
} else {
- idmapdlog(LOG_DEBUG,
- "Boring routing event");
+ if (DBG(CONFIG, 2)) {
+ idmapdlog(LOG_DEBUG,
+ "Boring routing event");
+ }
return (EVENT_NOTHING);
}
}
@@ -1023,6 +1216,7 @@ wait_for_event(struct timespec *timeoutp)
void *
idmap_cfg_update_thread(void *arg)
{
+ NOTE(ARGUNUSED(arg))
const ad_disc_t ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
@@ -1062,10 +1256,12 @@ idmap_cfg_update_thread(void *arg)
switch (wait_for_event(timeoutp)) {
case EVENT_NOTHING:
- idmapdlog(LOG_DEBUG, "Boring event.");
+ if (DBG(CONFIG, 2))
+ idmapdlog(LOG_DEBUG, "Boring event.");
continue;
case EVENT_REFRESH:
- idmapdlog(LOG_INFO, "SMF refresh");
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_INFO, "SMF refresh");
/*
* Blow away the ccache, we might have
* re-joined the domain or joined a new one
@@ -1073,11 +1269,14 @@ idmap_cfg_update_thread(void *arg)
(void) unlink(IDMAP_CACHEDIR "/ccache");
break;
case EVENT_DEGRADE:
- idmapdlog(LOG_DEBUG,
- "Service degraded");
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_DEBUG,
+ "Service degraded");
+ }
break;
case EVENT_TIMEOUT:
- idmapdlog(LOG_DEBUG, "TTL expired");
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_DEBUG, "TTL expired");
break;
case EVENT_ROUTING:
/* Already logged to DEBUG */
@@ -1157,29 +1356,40 @@ valid_ldap_attr(const char *attr) {
}
static
-int
-check_smf_debug_mode(idmap_cfg_handles_t *handles)
+void
+idmapd_set_debug(
+ idmap_cfg_handles_t *handles,
+ enum idmapd_debug item,
+ const char *name)
{
- boolean_t new_debug_mode;
- int rc;
+ int val;
- rc = prop_exists(handles, "debug", &new_debug_mode);
- if (rc != 0)
- return (rc);
+ if (item < 0 || item > IDMAPD_DEBUG_MAX)
+ return;
- if (_idmapdstate.debug_mode != new_debug_mode) {
- if (!_idmapdstate.debug_mode) {
- _idmapdstate.debug_mode = new_debug_mode;
- idmap_log_stderr(LOG_DEBUG);
- idmapdlog(LOG_DEBUG, "debug mode enabled");
- } else {
- idmapdlog(LOG_DEBUG, "debug mode disabled");
- idmap_log_stderr(-1);
- _idmapdstate.debug_mode = new_debug_mode;
- }
- }
+ val = get_debug(handles, name);
- return (0);
+ if (val != _idmapdstate.debug[item])
+ idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val);
+
+ _idmapdstate.debug[item] = val;
+}
+
+static
+void
+check_smf_debug_mode(idmap_cfg_handles_t *handles)
+{
+ idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all");
+ idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config");
+ idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping");
+ idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery");
+ idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns");
+ idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap");
+
+ adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]);
+ adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]);
+ adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]);
+ adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]);
}
/*
@@ -1206,18 +1416,26 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
return (-2);
}
- if (scf_pg_update(handles->general_pg) < 0) {
+ if (scf_pg_update(handles->debug_pg) < 0) {
idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
scf_strerror(scf_error()));
return (-2);
}
- rc = check_smf_debug_mode(handles);
+ check_smf_debug_mode(handles);
+
+ rc = get_val_bool(handles, "unresolvable_sid_mapping",
+ &pgcfg->eph_map_unres_sids, B_TRUE);
if (rc != 0)
(*errors)++;
- rc = get_val_int(handles, "unresolvable_sid_mapping",
- &pgcfg->eph_map_unres_sids, SCF_TYPE_BOOLEAN);
+ rc = get_val_bool(handles, "use_lsa",
+ &pgcfg->use_lsa, B_TRUE);
+ if (rc != 0)
+ (*errors)++;
+
+ rc = get_val_bool(handles, "disable_cross_forest_trusts",
+ &pgcfg->disable_cross_forest_trusts, B_TRUE);
if (rc != 0)
(*errors)++;
@@ -1249,6 +1467,11 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
if (rc != 0)
(*errors)++;
else {
+ if (pgcfg->domain_name != NULL &&
+ pgcfg->domain_name[0] == '\0') {
+ free(pgcfg->domain_name);
+ pgcfg->domain_name = NULL;
+ }
(void) ad_disc_set_DomainName(handles->ad_ctx,
pgcfg->domain_name);
pgcfg->domain_name_auto_disc = B_FALSE;
@@ -1276,8 +1499,8 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
/* If machine_sid not configured, generate one */
if (generate_machine_sid(&pgcfg->machine_sid) < 0)
return (-2);
- rc = set_val_astring(handles, "machine_sid",
- pgcfg->machine_sid);
+ rc = set_val_astring(handles, handles->config_pg,
+ "machine_sid", pgcfg->machine_sid);
if (rc != 0)
(*errors)++;
}
@@ -1368,19 +1591,19 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
}
+static
+void
+log_if_unable(const void *val, const char *what)
+{
+ if (val == NULL) {
+ idmapdlog(LOG_DEBUG, "unable to discover %s", what);
+ }
+}
-/*
- * This is the half of idmap_cfg_load() that auto-discovers values of
- * discoverable properties that weren't already set via SMF properties.
- *
- * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
- * needs to be careful not to overwrite any properties set in SMF.
- */
static
void
-idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
+discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx)
{
- ad_disc_t ad_ctx = handles->ad_ctx;
ad_disc_t trusted_ctx;
int i, j, k, l;
char *forestname;
@@ -1391,39 +1614,6 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
idmap_trustedforest_t *trustedforests;
ad_disc_domainsinforest_t *domainsinforest;
- idmapdlog(LOG_DEBUG, "Running discovery.");
-
- ad_disc_refresh(ad_ctx);
-
- if (pgcfg->default_domain == NULL)
- pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx,
- NULL);
-
- if (pgcfg->domain_name == NULL)
- pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx,
- &pgcfg->domain_name_auto_disc);
-
- if (pgcfg->domain_controller == NULL)
- pgcfg->domain_controller =
- ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE,
- &pgcfg->domain_controller_auto_disc);
-
- if (pgcfg->forest_name == NULL)
- pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
- &pgcfg->forest_name_auto_disc);
-
- if (pgcfg->site_name == NULL)
- pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
- &pgcfg->site_name_auto_disc);
-
- if (pgcfg->global_catalog == NULL)
- pgcfg->global_catalog =
- ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE,
- &pgcfg->global_catalog_auto_disc);
-
- pgcfg->domains_in_forest =
- ad_disc_get_DomainsInForest(ad_ctx, NULL);
-
pgcfg->trusted_domains =
ad_disc_get_TrustedDomains(ad_ctx, NULL);
@@ -1444,14 +1634,17 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
trusteddomain = pgcfg->trusted_domains[i].domain;
trusted_ctx = ad_disc_init();
- ad_disc_set_DomainName(trusted_ctx,
+ (void) ad_disc_set_DomainName(trusted_ctx,
trusteddomain);
forestname =
ad_disc_get_ForestName(trusted_ctx, NULL);
if (forestname == NULL) {
- idmapdlog(LOG_DEBUG, "unable to discover "
- "Forest Name for the trusted domain %s",
- trusteddomain);
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_DEBUG,
+ "unable to discover Forest Name"
+ " for the trusted domain %s",
+ trusteddomain);
+ }
ad_disc_fini(trusted_ctx);
continue;
}
@@ -1501,10 +1694,12 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
ad_disc_get_GlobalCatalog(trusted_ctx,
AD_DISC_PREFER_SITE, NULL);
if (globalcatalog == NULL) {
- idmapdlog(LOG_DEBUG,
- "unable to discover Global "
- "Catalog for the trusted domain %s",
- trusteddomain);
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_DEBUG,
+ "unable to discover Global Catalog"
+ " for the trusted domain %s",
+ trusteddomain);
+ }
free(forestname);
ad_disc_fini(trusted_ctx);
continue;
@@ -1513,10 +1708,12 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
ad_disc_get_DomainsInForest(trusted_ctx,
NULL);
if (domainsinforest == NULL) {
- idmapdlog(LOG_DEBUG,
- "unable to discover Domains in the Forest "
- "for the trusted domain %s",
- trusteddomain);
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_DEBUG,
+ "unable to discover Domains in the"
+ " Forest for the trusted domain %s",
+ trusteddomain);
+ }
free(globalcatalog);
free(forestname);
ad_disc_fini(trusted_ctx);
@@ -1545,25 +1742,75 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
free(trustedforests);
}
}
+}
- if (pgcfg->domain_name == NULL)
- idmapdlog(LOG_DEBUG, "unable to discover Domain Name");
- if (pgcfg->domain_controller == NULL)
- idmapdlog(LOG_DEBUG, "unable to discover Domain Controller");
- if (pgcfg->forest_name == NULL)
- idmapdlog(LOG_DEBUG, "unable to discover Forest Name");
- if (pgcfg->site_name == NULL)
- idmapdlog(LOG_DEBUG, "unable to discover Site Name");
- if (pgcfg->global_catalog == NULL)
- idmapdlog(LOG_DEBUG, "unable to discover Global Catalog");
- if (pgcfg->domains_in_forest == NULL)
- idmapdlog(LOG_DEBUG,
- "unable to discover Domains in the Forest");
- if (pgcfg->trusted_domains == NULL)
- idmapdlog(LOG_DEBUG, "unable to discover Trusted Domains");
+/*
+ * This is the half of idmap_cfg_load() that auto-discovers values of
+ * discoverable properties that weren't already set via SMF properties.
+ *
+ * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
+ * needs to be careful not to overwrite any properties set in SMF.
+ */
+static
+void
+idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
+{
+ ad_disc_t ad_ctx = handles->ad_ctx;
+
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_DEBUG, "Running discovery.");
+
+ ad_disc_refresh(ad_ctx);
+
+ if (pgcfg->domain_name == NULL) {
+ idmapdlog(LOG_DEBUG, "No domain name specified.");
+ } else {
+ if (pgcfg->domain_controller == NULL)
+ pgcfg->domain_controller =
+ ad_disc_get_DomainController(ad_ctx,
+ AD_DISC_PREFER_SITE,
+ &pgcfg->domain_controller_auto_disc);
+
+ if (pgcfg->forest_name == NULL)
+ pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
+ &pgcfg->forest_name_auto_disc);
+
+ if (pgcfg->site_name == NULL)
+ pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
+ &pgcfg->site_name_auto_disc);
+
+ if (pgcfg->global_catalog == NULL)
+ pgcfg->global_catalog =
+ ad_disc_get_GlobalCatalog(ad_ctx,
+ AD_DISC_PREFER_SITE,
+ &pgcfg->global_catalog_auto_disc);
+
+ pgcfg->domains_in_forest =
+ ad_disc_get_DomainsInForest(ad_ctx, NULL);
+
+ if (!pgcfg->disable_cross_forest_trusts)
+ discover_trusted_domains(pgcfg, ad_ctx);
+
+ if (DBG(CONFIG, 1)) {
+ log_if_unable(pgcfg->domain_name, "Domain Name");
+ log_if_unable(pgcfg->domain_controller,
+ "Domain Controller");
+ log_if_unable(pgcfg->forest_name, "Forest Name");
+ log_if_unable(pgcfg->site_name, "Site Name");
+ log_if_unable(pgcfg->global_catalog, "Global Catalog");
+ log_if_unable(pgcfg->domains_in_forest,
+ "Domains in the Forest");
+ if (!pgcfg->disable_cross_forest_trusts) {
+ log_if_unable(pgcfg->trusted_domains,
+ "Trusted Domains");
+ }
+ }
+ }
ad_disc_done(ad_ctx);
- idmapdlog(LOG_DEBUG, "Discovery done.");
+
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_DEBUG, "Discovery done.");
}
@@ -1574,18 +1821,16 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
* reads from SMF, but you still have to refresh the service after
* changing the config pg in order for the changes to take effect.
*
- * There are two flags:
+ * There is one flag:
*
* - CFG_DISCOVER
- * - CFG_LOG
*
* If CFG_DISCOVER is set then idmap_cfg_load() calls
* idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
* values that weren't set in SMF.
*
- * If CFG_LOG is set then idmap_cfg_load() will log (to LOG_NOTICE)
- * whether the configuration changed. This should be used only from the
- * refresh method.
+ * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration
+ * changed.
*
* Return values: 0 -> success, -1 -> failure, -2 -> hard failures
* reading from SMF.
@@ -1599,10 +1844,13 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags)
int ad_reload_required = 0;
idmap_pg_config_t new_pgcfg, *live_pgcfg;
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_DEBUG, "Loading configuration.");
+
live_pgcfg = &cfg->pgcfg;
(void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
- pthread_mutex_lock(&cfg->handles.mutex);
+ (void) pthread_mutex_lock(&cfg->handles.mutex);
if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
goto err;
@@ -1612,8 +1860,10 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags)
WRLOCK_CONFIG();
if (live_pgcfg->list_size_limit != new_pgcfg.list_size_limit) {
- idmapdlog(LOG_INFO, "change list_size=%d",
- new_pgcfg.list_size_limit);
+ if (DBG(CONFIG, 1)) {
+ idmapdlog(LOG_INFO, "change list_size=%d",
+ new_pgcfg.list_size_limit);
+ }
live_pgcfg->list_size_limit = new_pgcfg.list_size_limit;
}
@@ -1624,6 +1874,13 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags)
changed += update_bool(&live_pgcfg->eph_map_unres_sids,
&new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
+ changed += update_bool(&live_pgcfg->use_lsa,
+ &new_pgcfg.use_lsa, "use_lsa");
+
+ changed += update_bool(&live_pgcfg->disable_cross_forest_trusts,
+ &new_pgcfg.disable_cross_forest_trusts,
+ "disable_cross_forest_trusts");
+
changed += update_enum(&live_pgcfg->directory_based_mapping,
&new_pgcfg.directory_based_mapping, "directory_based_mapping",
directory_mapping_map);
@@ -1695,20 +1952,17 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags)
idmap_cfg_unload(&new_pgcfg);
- if (flags & CFG_LOG) {
- /*
- * If the config changes as a result of a refresh of the
- * service, then logging about it can provide useful
- * feedback to the sysadmin.
- */
- idmapdlog(LOG_NOTICE, "Configuration %schanged",
- changed ? "" : "un");
+ if (DBG(CONFIG, 1)) {
+ if (changed)
+ idmapdlog(LOG_NOTICE, "Configuration changed");
+ else
+ idmapdlog(LOG_NOTICE, "Configuration unchanged");
}
UNLOCK_CONFIG();
err:
- pthread_mutex_unlock(&cfg->handles.mutex);
+ (void) pthread_mutex_unlock(&cfg->handles.mutex);
if (rc < -1)
return (rc);
@@ -1749,7 +2003,7 @@ idmap_cfg_init()
if (!(handles->service = scf_service_create(handles->main)) ||
!(handles->instance = scf_instance_create(handles->main)) ||
!(handles->config_pg = scf_pg_create(handles->main)) ||
- !(handles->general_pg = scf_pg_create(handles->main))) {
+ !(handles->debug_pg = scf_pg_create(handles->main))) {
idmapdlog(LOG_ERR, "scf handle creation failed: %s",
scf_strerror(scf_error()));
goto error;
@@ -1769,14 +2023,13 @@ idmap_cfg_init()
}
if (scf_service_get_pg(handles->service,
- GENERAL_PG, handles->general_pg) < 0) {
- idmapdlog(LOG_ERR, "scf_service_get_pg() failed: %s",
- scf_strerror(scf_error()));
+ DEBUG_PG, handles->debug_pg) < 0) {
+ idmapdlog(LOG_ERR, "Property group \"%s\": %s",
+ DEBUG_PG, scf_strerror(scf_error()));
goto error;
}
- if (check_smf_debug_mode(handles) != 0)
- goto error;
+ check_smf_debug_mode(handles);
/* Initialize AD Auto Discovery context */
handles->ad_ctx = ad_disc_init();
@@ -1852,7 +2105,8 @@ idmap_cfg_fini(idmap_cfg_t *cfg)
(void) pthread_mutex_destroy(&handles->mutex);
scf_pg_destroy(handles->config_pg);
- scf_pg_destroy(handles->general_pg);
+ if (handles->debug_pg != NULL)
+ scf_pg_destroy(handles->debug_pg);
scf_instance_destroy(handles->instance);
scf_service_destroy(handles->service);
scf_handle_destroy(handles->main);
@@ -1879,6 +2133,47 @@ idmap_cfg_hup_handler(int sig)
}
/*
+ * Upgrade the debug flags.
+ *
+ * We're replacing a single debug flag with a fine-grained mechanism that
+ * is also capable of considerably more verbosity. We'll take a stab at
+ * producing roughly the same level of output.
+ */
+static
+int
+upgrade_debug(idmap_cfg_handles_t *handles)
+{
+ boolean_t debug_present;
+ const char DEBUG_PROP[] = "debug";
+ int rc;
+
+ rc = prop_exists(handles, DEBUG_PROP, &debug_present);
+
+ if (rc != 0)
+ return (rc);
+
+ if (!debug_present)
+ return (0);
+
+ idmapdlog(LOG_INFO,
+ "Upgrading old %s/%s setting to %s/* settings.",
+ CONFIG_PG, DEBUG_PROP, DEBUG_PG);
+
+ rc = set_val_integer(handles, handles->debug_pg, "config", 1);
+ if (rc != 0)
+ return (rc);
+ rc = set_val_integer(handles, handles->debug_pg, "discovery", 1);
+ if (rc != 0)
+ return (rc);
+
+ rc = del_val(handles, handles->config_pg, DEBUG_PROP);
+ if (rc != 0)
+ return (rc);
+
+ return (0);
+}
+
+/*
* Upgrade the DS mapping flags.
*
* If the old ds_name_mapping_enabled flag is present, then
@@ -1908,8 +2203,8 @@ upgrade_directory_mapping(idmap_cfg_handles_t *handles)
return (0);
boolean_t legacy_ds_name_mapping_enabled;
- rc = get_val_int(handles, DS_NAME_MAPPING_ENABLED,
- &legacy_ds_name_mapping_enabled, SCF_TYPE_BOOLEAN);
+ rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED,
+ &legacy_ds_name_mapping_enabled, B_FALSE);
if (rc != 0)
return (rc);
@@ -1935,8 +2230,8 @@ upgrade_directory_mapping(idmap_cfg_handles_t *handles)
"to %s=%s.",
DS_NAME_MAPPING_ENABLED, legacy_bool_string,
DIRECTORY_BASED_MAPPING, legacy_mode);
- rc = set_val_astring(handles, DIRECTORY_BASED_MAPPING,
- legacy_mode);
+ rc = set_val_astring(handles, handles->config_pg,
+ DIRECTORY_BASED_MAPPING, legacy_mode);
if (rc != 0)
return (rc);
} else {
@@ -1962,7 +2257,7 @@ upgrade_directory_mapping(idmap_cfg_handles_t *handles)
free(directory_based_mapping);
}
- rc = del_val(handles, DS_NAME_MAPPING_ENABLED);
+ rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED);
if (rc != 0)
return (rc);
@@ -1982,5 +2277,9 @@ idmap_cfg_upgrade(idmap_cfg_t *cfg)
if (rc != 0)
return (rc);
+ rc = upgrade_debug(&cfg->handles);
+ if (rc != 0)
+ return (rc);
+
return (0);
}
diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.h b/usr/src/cmd/idmap/idmapd/idmap_config.h
index bdee366906..eb1c7ffb69 100644
--- a/usr/src/cmd/idmap/idmapd/idmap_config.h
+++ b/usr/src/cmd/idmap/idmapd/idmap_config.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _IDMAP_CONFIG_H
@@ -57,7 +56,7 @@ typedef struct idmap_cfg_handles {
scf_instance_t *instance;
scf_service_t *service;
scf_propertygroup_t *config_pg;
- scf_propertygroup_t *general_pg;
+ scf_propertygroup_t *debug_pg;
ad_disc_t ad_ctx;
} idmap_cfg_handles_t;
@@ -106,6 +105,8 @@ typedef struct idmap_pg_config {
char *nldap_winname_attr;
int directory_based_mapping; /* enum */
boolean_t eph_map_unres_sids;
+ boolean_t use_lsa;
+ boolean_t disable_cross_forest_trusts;
} idmap_pg_config_t;
typedef struct idmap_cfg {
diff --git a/usr/src/cmd/idmap/idmapd/idmap_lsa.c b/usr/src/cmd/idmap/idmapd/idmap_lsa.c
new file mode 100644
index 0000000000..256e8494d8
--- /dev/null
+++ b/usr/src/cmd/idmap/idmapd/idmap_lsa.c
@@ -0,0 +1,237 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * LSA lookups
+ */
+
+#include <stdio.h>
+#include <note.h>
+#include <assert.h>
+
+#include "idmapd.h"
+#include "libsmb.h"
+
+idmap_retcode
+idmap_lsa_xlate_sid_type(const lsa_account_t *acct, idmap_id_type *ret_type)
+{
+ switch (acct->a_sidtype) {
+ case SidTypeUser:
+ case SidTypeComputer:
+ case SidTypeDomain:
+ case SidTypeDeletedAccount:
+ case SidTypeUnknown:
+ case SidTypeLabel:
+ *ret_type = IDMAP_USID;
+ return (IDMAP_SUCCESS);
+ case SidTypeGroup:
+ case SidTypeAlias:
+ case SidTypeWellKnownGroup:
+ *ret_type = IDMAP_GSID;
+ return (IDMAP_SUCCESS);
+ case SidTypeNull:
+ case SidTypeInvalid:
+ default:
+ idmapdlog(LOG_WARNING,
+ "LSA lookup: bad type %d for %s@%s",
+ acct->a_sidtype, acct->a_name, acct->a_domain);
+ return (IDMAP_ERR_OTHER);
+ }
+ NOTE(NOTREACHED)
+}
+
+/* Given SID, look up name and type */
+idmap_retcode
+lookup_lsa_by_sid(
+ const char *sidprefix,
+ uint32_t rid,
+ char **ret_name,
+ char **ret_domain,
+ idmap_id_type *ret_type)
+{
+ lsa_account_t acct;
+ char sid[SMB_SID_STRSZ + 1];
+ idmap_retcode ret;
+ int rc;
+
+ (void) memset(&acct, 0, sizeof (acct));
+ *ret_name = NULL;
+ *ret_domain = NULL;
+
+ (void) snprintf(sid, sizeof (sid), "%s-%u", sidprefix, rid);
+
+ rc = smb_lookup_sid(sid, &acct);
+ if (rc != 0) {
+ idmapdlog(LOG_ERR, "Error: smb_lookup_sid failed.");
+ idmapdlog(LOG_ERR,
+ "Check SMB service (svc:/network/smb/server).");
+ idmapdlog(LOG_ERR,
+ "Check connectivity to Active Directory.");
+
+ ret = IDMAP_ERR_OTHER;
+ goto out;
+ }
+ if (acct.a_status == NT_STATUS_NONE_MAPPED) {
+ ret = IDMAP_ERR_NOTFOUND;
+ goto out;
+ }
+ if (acct.a_status != NT_STATUS_SUCCESS) {
+ idmapdlog(LOG_WARNING,
+ "Warning: smb_lookup_sid(%s) failed (0x%x)",
+ sid, acct.a_status);
+ /* Fail soft */
+ ret = IDMAP_ERR_NOTFOUND;
+ goto out;
+ }
+
+ ret = idmap_lsa_xlate_sid_type(&acct, ret_type);
+ if (ret != IDMAP_SUCCESS)
+ goto out;
+
+ *ret_name = strdup(acct.a_name);
+ if (*ret_name == NULL) {
+ ret = IDMAP_ERR_MEMORY;
+ goto out;
+ }
+
+ *ret_domain = strdup(acct.a_domain);
+ if (*ret_domain == NULL) {
+ ret = IDMAP_ERR_MEMORY;
+ goto out;
+ }
+
+ ret = IDMAP_SUCCESS;
+
+out:
+ if (ret != IDMAP_SUCCESS) {
+ free(*ret_name);
+ *ret_name = NULL;
+ free(*ret_domain);
+ *ret_domain = NULL;
+ }
+ return (ret);
+}
+
+/* Given name and optional domain, look up SID, type, and canonical name */
+idmap_retcode
+lookup_lsa_by_name(
+ const char *name,
+ const char *domain,
+ char **ret_sidprefix,
+ uint32_t *ret_rid,
+ char **ret_name,
+ char **ret_domain,
+ idmap_id_type *ret_type)
+{
+ lsa_account_t acct;
+ char *namedom = NULL;
+ idmap_retcode ret;
+ int rc;
+
+ (void) memset(&acct, 0, sizeof (acct));
+ *ret_sidprefix = NULL;
+ if (ret_name != NULL)
+ *ret_name = NULL;
+ if (ret_domain != NULL)
+ *ret_domain = NULL;
+
+ if (domain != NULL)
+ (void) asprintf(&namedom, "%s@%s", name, domain);
+ else
+ namedom = strdup(name);
+ if (namedom == NULL) {
+ ret = IDMAP_ERR_MEMORY;
+ goto out;
+ }
+
+ rc = smb_lookup_name(namedom, SidTypeUnknown, &acct);
+ if (rc != 0) {
+ idmapdlog(LOG_ERR, "Error: smb_lookup_name failed.");
+ idmapdlog(LOG_ERR,
+ "Check SMB service (svc:/network/smb/server).");
+ idmapdlog(LOG_ERR,
+ "Check connectivity to Active Directory.");
+ ret = IDMAP_ERR_OTHER;
+ goto out;
+ }
+ if (acct.a_status == NT_STATUS_NONE_MAPPED) {
+ ret = IDMAP_ERR_NOTFOUND;
+ goto out;
+ }
+ if (acct.a_status != NT_STATUS_SUCCESS) {
+ idmapdlog(LOG_WARNING,
+ "Warning: smb_lookup_name(%s) failed (0x%x)",
+ namedom, acct.a_status);
+ /* Fail soft */
+ ret = IDMAP_ERR_NOTFOUND;
+ goto out;
+ }
+
+ rc = smb_sid_splitstr(acct.a_sid, ret_rid);
+ assert(rc == 0);
+ *ret_sidprefix = strdup(acct.a_sid);
+ if (*ret_sidprefix == NULL) {
+ ret = IDMAP_ERR_MEMORY;
+ goto out;
+ }
+
+ ret = idmap_lsa_xlate_sid_type(&acct, ret_type);
+ if (ret != IDMAP_SUCCESS)
+ goto out;
+
+ if (ret_name != NULL) {
+ *ret_name = strdup(acct.a_name);
+ if (*ret_name == NULL) {
+ ret = IDMAP_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ if (ret_domain != NULL) {
+ *ret_domain = strdup(acct.a_domain);
+ if (*ret_domain == NULL) {
+ ret = IDMAP_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ ret = IDMAP_SUCCESS;
+
+out:
+ free(namedom);
+ if (ret != IDMAP_SUCCESS) {
+ if (ret_name != NULL) {
+ free(*ret_name);
+ *ret_name = NULL;
+ }
+ if (ret_domain != NULL) {
+ free(*ret_domain);
+ *ret_domain = NULL;
+ }
+ free(*ret_sidprefix);
+ *ret_sidprefix = NULL;
+ }
+ return (ret);
+}
diff --git a/usr/src/cmd/idmap/idmapd/idmap_lsa.h b/usr/src/cmd/idmap/idmapd/idmap_lsa.h
new file mode 100644
index 0000000000..5dae07a6ab
--- /dev/null
+++ b/usr/src/cmd/idmap/idmapd/idmap_lsa.h
@@ -0,0 +1,53 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef IDMAP_LSA_H
+#define IDMAP_LSA_H
+
+/*
+ * LSA lookups
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rpcsvc/idmap_prot.h>
+
+/* Given SID, look up name and type */
+idmap_retcode
+lookup_lsa_by_sid(const char *sidprefix, uint32_t rid, char **ret_name,
+ char **ret_domain, idmap_id_type *ret_type);
+
+/* Given name and optional domain, look up SID, type, and canonical name */
+idmap_retcode lookup_lsa_by_name(const char *name, const char *domain,
+ char **ret_sidprefix, uint32_t *ret_rid, char **ret_name,
+ char **ret_domain, idmap_id_type *ret_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDMAP_LSA_H */
diff --git a/usr/src/cmd/idmap/idmapd/idmapd.c b/usr/src/cmd/idmap/idmapd/idmapd.c
index 5ea3292acd..828bfc6545 100644
--- a/usr/src/cmd/idmap/idmapd/idmapd.c
+++ b/usr/src/cmd/idmap/idmapd/idmapd.c
@@ -53,6 +53,9 @@
#include <sys/sid.h>
#include <sys/idmap.h>
#include <pthread.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <note.h>
static void term_handler(int);
static void init_idmapd();
@@ -63,31 +66,13 @@ idmapd_state_t _idmapdstate;
SVCXPRT *xprt = NULL;
static int dfd = -1; /* our door server fildes, for unregistration */
-static int degraded = 0; /* whether the FMRI has been marked degraded */
+static boolean_t degraded = B_FALSE;
static uint32_t num_threads = 0;
static pthread_key_t create_threads_key;
static uint32_t max_threads = 40;
-
-/*
- * The following structure determines where the log messages from idmapdlog()
- * go to. It can be stderr (idmapd -d) and/or the real idmapdlog (idmapd).
- *
- * logstate.max_pri is integer cutoff necessary to silence low-priority
- * messages to stderr. idmapdlog has its own means so there a boolean
- * logstate.write_idmapdlog is enough.
- *
- * logstate.degraded is a mode used by idmapd in its degraded state.
- */
-
-static struct {
- boolean_t write_syslog;
- int max_pri; /* Max priority written to stderr */
- boolean_t degraded;
-} logstate = {B_FALSE, LOG_DEBUG, B_FALSE};
-
/*
* Server door thread start routine.
*
@@ -193,16 +178,8 @@ term_handler(int sig)
static void
usr1_handler(int sig)
{
- boolean_t saved_debug_mode = _idmapdstate.debug_mode;
-
- _idmapdstate.debug_mode = B_TRUE;
- idmap_log_stderr(LOG_DEBUG);
-
+ NOTE(ARGUNUSED(sig))
print_idmapdstate();
-
- _idmapdstate.debug_mode = saved_debug_mode;
- idmap_log_stderr(_idmapdstate.daemon_mode ? -1 : LOG_DEBUG);
-
}
static int pipe_fd = -1;
@@ -274,7 +251,6 @@ main(int argc, char **argv)
struct rlimit rl;
_idmapdstate.daemon_mode = TRUE;
- _idmapdstate.debug_mode = FALSE;
while ((c = getopt(argc, argv, "d")) != -1) {
switch (c) {
case 'd':
@@ -293,8 +269,6 @@ main(int argc, char **argv)
idmap_set_logger(idmapdlog);
adutils_set_logger(idmapdlog);
- idmap_log_syslog(B_TRUE);
- idmap_log_stderr(_idmapdstate.daemon_mode ? -1 : LOG_DEBUG);
if (is_system_labeled() && getzoneid() != GLOBAL_ZONEID) {
idmapdlog(LOG_ERR,
@@ -373,7 +347,7 @@ init_idmapd()
* one.
*/
(void) unlink(IDMAP_CACHEDIR "/ccache");
- putenv("KRB5CCNAME=" IDMAP_CACHEDIR "/ccache");
+ (void) putenv("KRB5CCNAME=" IDMAP_CACHEDIR "/ccache");
if (sysinfo(SI_HOSTNAME, _idmapdstate.hostname,
sizeof (_idmapdstate.hostname)) == -1) {
@@ -433,7 +407,8 @@ init_idmapd()
_idmapdstate.limit_gid = _idmapdstate.next_gid + 8192;
}
- print_idmapdstate();
+ if (DBG(CONFIG, 1))
+ print_idmapdstate();
return;
@@ -445,7 +420,7 @@ errout:
static void
fini_idmapd()
{
- __idmap_unreg(dfd);
+ (void) __idmap_unreg(dfd);
fini_mapping_system();
if (xprt != NULL)
svc_destroy(xprt);
@@ -492,13 +467,10 @@ degrade_svc(int poke_discovery, const char *reason)
if (degraded)
return;
- idmapdlog(LOG_ERR, "Degraded operation (%s). If you are running an "
- "SMB server in workgroup mode, or if you're not running an SMB "
- "server, then you can ignore this message", reason);
+ idmapdlog(LOG_ERR, "Degraded operation (%s).", reason);
membar_producer();
- degraded = 1;
- idmap_log_degraded(B_TRUE);
+ degraded = B_TRUE;
if ((fmri = get_fmri()) != NULL)
(void) smf_degrade_instance(fmri, 0);
@@ -524,8 +496,7 @@ restore_svc(void)
(void) smf_restore_instance(fmri);
membar_producer();
- degraded = 0;
- idmap_log_degraded(B_FALSE);
+ degraded = B_FALSE;
idmapdlog(LOG_NOTICE, "Normal operation restored");
}
@@ -536,41 +507,152 @@ void
idmapdlog(int pri, const char *format, ...) {
va_list args;
- if (pri <= logstate.max_pri) {
- va_start(args, format);
- (void) vfprintf(stderr, format, args);
- (void) fprintf(stderr, "\n");
- va_end(args);
- }
+ va_start(args, format);
+ (void) vfprintf(stderr, format, args);
+ (void) fprintf(stderr, "\n");
+ va_end(args);
/*
* We don't want to fill up the logs with useless messages when
* we're degraded, but we still want to log.
*/
- if (logstate.degraded)
+ if (degraded)
pri = LOG_DEBUG;
- if (logstate.write_syslog) {
- va_start(args, format);
- vsyslog(pri, format, args);
- va_end(args);
- }
+ va_start(args, format);
+ vsyslog(pri, format, args);
+ va_end(args);
}
-void
-idmap_log_stderr(int pri)
+static void
+trace_str(nvlist_t *entry, char *n1, char *n2, char *str)
{
- logstate.max_pri = pri;
+ char name[IDMAP_TRACE_NAME_MAX+1]; /* Max used is only about 11 */
+
+ (void) strlcpy(name, n1, sizeof (name));
+ if (n2 != NULL)
+ (void) strlcat(name, n2, sizeof (name));
+
+ (void) nvlist_add_string(entry, name, str);
}
-void
-idmap_log_syslog(boolean_t what)
+static void
+trace_int(nvlist_t *entry, char *n1, char *n2, int64_t i)
{
- logstate.write_syslog = what;
+ char name[IDMAP_TRACE_NAME_MAX+1]; /* Max used is only about 11 */
+
+ (void) strlcpy(name, n1, sizeof (name));
+ if (n2 != NULL)
+ (void) strlcat(name, n2, sizeof (name));
+
+ (void) nvlist_add_int64(entry, name, i);
}
-void
-idmap_log_degraded(boolean_t what)
+static void
+trace_sid(nvlist_t *entry, char *n1, char *n2, idmap_sid *sid)
+{
+ char *str;
+
+ (void) asprintf(&str, "%s-%u", sid->prefix, sid->rid);
+ if (str == NULL)
+ return;
+
+ trace_str(entry, n1, n2, str);
+ free(str);
+}
+
+static void
+trace_id(nvlist_t *entry, char *fromto, idmap_id *id, char *name, char *domain)
+{
+ trace_int(entry, fromto, IDMAP_TRACE_TYPE, (int64_t)id->idtype);
+ if (IS_ID_SID(*id)) {
+ if (name != NULL) {
+ char *str;
+
+ (void) asprintf(&str, "%s%s%s", name,
+ domain == NULL ? "" : "@",
+ domain == NULL ? "" : domain);
+ if (str != NULL) {
+ trace_str(entry, fromto, IDMAP_TRACE_NAME, str);
+ free(str);
+ }
+ }
+ if (id->idmap_id_u.sid.prefix != NULL) {
+ trace_sid(entry, fromto, IDMAP_TRACE_SID,
+ &id->idmap_id_u.sid);
+ }
+ } else if (IS_ID_POSIX(*id)) {
+ if (name != NULL)
+ trace_str(entry, fromto, IDMAP_TRACE_NAME, name);
+ if (id->idmap_id_u.uid != IDMAP_SENTINEL_PID) {
+ trace_int(entry, fromto, IDMAP_TRACE_UNIXID,
+ (int64_t)id->idmap_id_u.uid);
+ }
+ }
+}
+
+/*
+ * Record a trace event. TRACE() has already decided whether or not
+ * tracing is required; what we do here is collect the data and send it
+ * to its destination - to the trace log in the response, if
+ * IDMAP_REQ_FLG_TRACE is set, and to the SMF service log, if debug/mapping
+ * is greater than zero.
+ */
+int
+trace(idmap_mapping *req, idmap_id_res *res, char *fmt, ...)
{
- logstate.degraded = what;
+ va_list va;
+ char *buf;
+ int err;
+ nvlist_t *entry;
+
+ assert(req != NULL);
+ assert(res != NULL);
+
+ err = nvlist_alloc(&entry, NV_UNIQUE_NAME, 0);
+ if (err != 0) {
+ (void) fprintf(stderr, "trace nvlist_alloc(entry): %s\n",
+ strerror(err));
+ return (0);
+ }
+
+ trace_id(entry, "from", &req->id1, req->id1name, req->id1domain);
+ trace_id(entry, "to", &res->id, req->id2name, req->id2domain);
+
+ if (IDMAP_ERROR(res->retcode)) {
+ trace_int(entry, IDMAP_TRACE_ERROR, NULL,
+ (int64_t)res->retcode);
+ }
+
+ va_start(va, fmt);
+ (void) vasprintf(&buf, fmt, va);
+ va_end(va);
+ if (buf != NULL) {
+ trace_str(entry, IDMAP_TRACE_MESSAGE, NULL, buf);
+ free(buf);
+ }
+
+ if (DBG(MAPPING, 1))
+ idmap_trace_print_1(stderr, "", entry);
+
+ if (req->flag & IDMAP_REQ_FLG_TRACE) {
+ /* Lazily allocate the trace list */
+ if (res->info.trace == NULL) {
+ err = nvlist_alloc(&res->info.trace, 0, 0);
+ if (err != 0) {
+ res->info.trace = NULL; /* just in case */
+ (void) fprintf(stderr,
+ "trace nvlist_alloc(trace): %s\n",
+ strerror(err));
+ nvlist_free(entry);
+ return (0);
+ }
+ }
+ (void) nvlist_add_nvlist(res->info.trace, "", entry);
+ /* Note that entry is copied, so we must still free our copy */
+ }
+
+ nvlist_free(entry);
+
+ return (0);
}
diff --git a/usr/src/cmd/idmap/idmapd/idmapd.h b/usr/src/cmd/idmap/idmapd/idmapd.h
index fe62e0468b..4e59ee49ae 100644
--- a/usr/src/cmd/idmap/idmapd/idmapd.h
+++ b/usr/src/cmd/idmap/idmapd/idmapd.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _IDMAPD_H
@@ -59,13 +58,41 @@ typedef enum idmap_namemap_mode {
} idmap_namemap_mode_t;
/*
+ * Debugging output.
+ *
+ * There are some number of areas - configuration, mapping, discovery, et
+ * cetera - and for each area there is a verbosity level controlled through
+ * an SMF property. The default is zero, and "debug/all" provides a master
+ * control allowing you to turn on all debugging output with one setting.
+ *
+ * A typical debugging output sequence would look like
+ *
+ * if (DBG(CONFIG, 2)) {
+ * idmapdlog(LOG_DEBUG,
+ * "some message about config at verbosity 2");
+ * }
+ */
+enum idmapd_debug {
+ IDMAPD_DEBUG_ALL = 0,
+ IDMAPD_DEBUG_CONFIG = 1,
+ IDMAPD_DEBUG_MAPPING = 2,
+ IDMAPD_DEBUG_DISC = 3,
+ IDMAPD_DEBUG_DNS = 4,
+ IDMAPD_DEBUG_LDAP = 5,
+ IDMAPD_DEBUG_MAX = 5
+};
+
+#define DBG(type, lev) \
+ (_idmapdstate.debug[IDMAPD_DEBUG_##type] >= (lev) || \
+ _idmapdstate.debug[IDMAPD_DEBUG_ALL] >= (lev))
+
+/*
* Global state of idmapd daemon.
*/
typedef struct idmapd_state {
rwlock_t rwlk_cfg; /* config lock */
idmap_cfg_t *cfg; /* config */
bool_t daemon_mode;
- bool_t debug_mode;
char hostname[MAX_NAME_LEN]; /* my hostname */
uid_t next_uid;
gid_t next_gid;
@@ -76,6 +103,7 @@ typedef struct idmapd_state {
adutils_ad_t **gcs;
int num_dcs;
adutils_ad_t **dcs;
+ int debug[IDMAPD_DEBUG_MAX+1];
} idmapd_state_t;
extern idmapd_state_t _idmapdstate;
@@ -207,30 +235,24 @@ typedef struct wksids_table {
#define IDMAP_DBNAME IDMAP_DBDIR "/idmap.db"
#define IDMAP_CACHENAME IDMAP_CACHEDIR "/idmap.db"
-#define IS_BATCH_SID(batch, i) \
- (batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_SID || \
- batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_USID || \
- batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_GSID)
-
-#define IS_BATCH_UID(batch, i) \
- (batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_UID)
-
-#define IS_BATCH_GID(batch, i) \
- (batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_GID)
+#define IS_ID_NONE(id) \
+ ((id).idtype == IDMAP_NONE)
#define IS_ID_SID(id) \
((id).idtype == IDMAP_SID || \
(id).idtype == IDMAP_USID || \
(id).idtype == IDMAP_GSID) \
-#define IS_REQUEST_SID(req, n) IS_ID_SID((req).id##n)
-
+#define IS_ID_UID(id) \
+ ((id).idtype == IDMAP_UID)
-#define IS_REQUEST_UID(request) \
- ((request).id1.idtype == IDMAP_UID)
+#define IS_ID_GID(id) \
+ ((id).idtype == IDMAP_GID)
-#define IS_REQUEST_GID(request) \
- ((request).id1.idtype == IDMAP_GID)
+#define IS_ID_POSIX(id) \
+ ((id).idtype == IDMAP_UID || \
+ (id).idtype == IDMAP_GID || \
+ (id).idtype == IDMAP_POSIXID) \
/*
* Local RID ranges
@@ -240,6 +262,32 @@ typedef struct wksids_table {
#define LOCALRID_GID_MIN (((uint32_t)INT32_MAX) + 1)
#define LOCALRID_GID_MAX UINT32_MAX
+/*
+ * Tracing.
+ *
+ * The tracing mechanism is intended to help the administrator understand
+ * why their mapping configuration is doing what it is. Each interesting
+ * decision point during the mapping process calls TRACE() with the current
+ * request and response and a printf-style message. The message, plus
+ * data from the request and the response, is logged to the service log
+ * (if debug/mapping is greater than zero) or reported to the caller
+ * (if IDMAP_REQ_FLG_TRACE was set in the request. The primary consumer
+ * is the "-V" option to "idmap show".
+ *
+ * TRACING(req) says whether tracing is appropriate for the request, and
+ * is used to determine and record whether any request in a batch requested
+ * tracing, to control whether later code loops over the batch to do tracing
+ * for any of the requests.
+ *
+ * TRACE(req, res, fmt, ...) generates a trace entry if appropriate.
+ */
+#define TRACING(req) \
+ (DBG(MAPPING, 1) || \
+ ((req)->flag & IDMAP_REQ_FLG_TRACE) != 0)
+#define TRACE(req, res, ...) \
+ ((void)(TRACING(req) && trace(req, res, __VA_ARGS__)))
+extern int trace(idmap_mapping *req, idmap_id_res *res, char *fmt, ...);
+
typedef idmap_retcode (*update_list_res_cb)(void *, const char **, uint64_t);
typedef int (*list_svc_cb)(void *, int, char **, char **);
@@ -251,7 +299,7 @@ extern void print_idmapdstate();
extern int create_directory(const char *, uid_t, gid_t);
extern int load_config();
extern void reload_ad();
-extern int idmap_init_tsd_key(void);
+extern void idmap_init_tsd_key(void);
extern void degrade_svc(int, const char *);
extern void restore_svc(void);
@@ -294,22 +342,19 @@ extern void cleanup_lookup_state(lookup_state_t *);
extern idmap_retcode ad_lookup_batch(lookup_state_t *,
idmap_mapping_batch *, idmap_ids_res *);
extern idmap_retcode lookup_name2sid(sqlite *, const char *, const char *,
- int *, char **, char **, char **,
- idmap_rid_t *, idmap_mapping *, int);
+ int, char **, char **, char **,
+ idmap_rid_t *, idmap_id_type *,
+ idmap_mapping *, int);
extern idmap_retcode lookup_wksids_name2sid(const char *, const char *,
char **, char **, char **, idmap_rid_t *,
- int *);
+ idmap_id_type *);
extern idmap_retcode idmap_cache_flush(idmap_flush_op);
-extern void idmap_log_stderr(int);
-extern void idmap_log_syslog(boolean_t);
-extern void idmap_log_degraded(boolean_t);
-
extern const wksids_table_t *find_wksid_by_pid(posix_id_t pid, int is_user);
extern const wksids_table_t *find_wksid_by_sid(const char *sid, int rid,
- int type);
+ idmap_id_type type);
extern const wksids_table_t *find_wksid_by_name(const char *name,
- const char *domain, int type);
+ const char *domain, idmap_id_type type);
extern const wksids_table_t *find_wk_by_sid(char *sid);
#ifdef __cplusplus
diff --git a/usr/src/cmd/idmap/idmapd/init.c b/usr/src/cmd/idmap/idmapd/init.c
index c661ede558..43c18b6293 100644
--- a/usr/src/cmd/idmap/idmapd/init.c
+++ b/usr/src/cmd/idmap/idmapd/init.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -100,7 +99,8 @@ load_config()
return (rc);
}
- idmapdlog(LOG_DEBUG, "Initial configuration loaded");
+ if (DBG(CONFIG, 1))
+ idmapdlog(LOG_DEBUG, "Initial configuration loaded");
return (0);
}
@@ -111,14 +111,21 @@ reload_gcs()
{
int i, j;
adutils_ad_t **new_gcs;
- adutils_ad_t **old_gcs;
+ adutils_ad_t **old_gcs = _idmapdstate.gcs;
int new_num_gcs;
- int old_num_gcs;
+ int old_num_gcs = _idmapdstate.num_gcs;
idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
idmap_trustedforest_t *trustfor = pgcfg->trusted_forests;
int num_trustfor = pgcfg->num_trusted_forests;
ad_disc_domainsinforest_t *domain_in_forest;
+ if (pgcfg->domain_name == NULL) {
+ /* No domain name specified - workgroup mode. */
+ new_gcs = NULL;
+ new_num_gcs = 0;
+ goto out;
+ }
+
if (pgcfg->global_catalog == NULL ||
pgcfg->global_catalog[0].host[0] == '\0') {
/*
@@ -132,9 +139,6 @@ reload_gcs()
return;
}
- old_gcs = _idmapdstate.gcs;
- old_num_gcs = _idmapdstate.num_gcs;
-
new_num_gcs = 1 + num_trustfor;
new_gcs = calloc(new_num_gcs, sizeof (adutils_ad_t *));
if (new_gcs == NULL) {
@@ -220,7 +224,6 @@ out:
_idmapdstate.gcs = new_gcs;
_idmapdstate.num_gcs = new_num_gcs;
-
if (old_gcs != NULL) {
for (i = 0; i < old_num_gcs; i++)
adutils_ad_free(&old_gcs[i]);
@@ -240,11 +243,18 @@ reload_dcs(void)
{
int i;
adutils_ad_t **new_dcs;
- adutils_ad_t **old_dcs;
+ adutils_ad_t **old_dcs = _idmapdstate.dcs;
int new_num_dcs;
- int old_num_dcs;
+ int old_num_dcs = _idmapdstate.num_dcs;
idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
+ if (pgcfg->domain_name == NULL) {
+ /* No domain name specified - workgroup mode. */
+ new_dcs = NULL;
+ new_num_dcs = 0;
+ goto out;
+ }
+
if (pgcfg->domain_controller == NULL ||
pgcfg->domain_controller[0].host[0] == '\0') {
/*
@@ -258,9 +268,6 @@ reload_dcs(void)
return;
}
- old_dcs = _idmapdstate.dcs;
- old_num_dcs = _idmapdstate.num_dcs;
-
new_num_dcs = 1;
new_dcs = calloc(new_num_dcs, sizeof (adutils_ad_t *));
if (new_dcs == NULL)
@@ -295,6 +302,7 @@ reload_dcs(void)
}
}
+out:
_idmapdstate.dcs = new_dcs;
_idmapdstate.num_dcs = new_num_dcs;
@@ -325,7 +333,7 @@ reload_ad(void)
}
void
-print_idmapdstate()
+print_idmapdstate(void)
{
int i, j;
idmap_pg_config_t *pgcfg;
diff --git a/usr/src/cmd/idmap/idmapd/nldaputils.c b/usr/src/cmd/idmap/idmapd/nldaputils.c
index e14d47e2bb..2895789bd3 100644
--- a/usr/src/cmd/idmap/idmapd/nldaputils.c
+++ b/usr/src/cmd/idmap/idmapd/nldaputils.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -721,7 +720,7 @@ nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
idmap_ids_res *result)
{
idmap_retcode retcode, rc1;
- int i, add, is_wuser;
+ int i, add;
idmap_mapping *req;
idmap_id_res *res;
idmap_nldap_query_state_t *qs = NULL;
@@ -751,7 +750,7 @@ nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
if (!(req->direction & _IDMAP_F_LOOKUP_NLDAP))
continue;
- if (IS_REQUEST_SID(*req, 1)) {
+ if (IS_ID_SID(req->id1)) {
/* win2unix request: */
@@ -779,7 +778,7 @@ nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
/* Lookup nldap by winname to get pid and unixname */
add = 1;
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
res->info.src = IDMAP_MAP_SRC_NEW;
how = &res->info.how;
how->map_type = IDMAP_MAP_TYPE_DS_NLDAP;
@@ -792,7 +791,7 @@ nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
&req->id2name, &res->id.idmap_id_u.uid,
&res->retcode);
- } else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) {
+ } else if (IS_ID_UID(req->id1) || IS_ID_GID(req->id1)) {
/* unix2win request: */
@@ -807,7 +806,7 @@ nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
req->id2domain = NULL;
/* Set how info */
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
res->info.src = IDMAP_MAP_SRC_NEW;
how = &res->info.how;
how->map_type = IDMAP_MAP_TYPE_DS_NLDAP;
@@ -887,18 +886,16 @@ out:
if (res->retcode == IDMAP_SUCCESS &&
req->id2name != NULL &&
res->id.idmap_id_u.sid.prefix == NULL &&
- (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req))) {
+ (IS_ID_UID(req->id1) || IS_ID_GID(req->id1))) {
- is_wuser = -1;
rc1 = lookup_name2sid(state->cache,
- req->id2name, req->id2domain, &is_wuser,
+ req->id2name, req->id2domain, -1,
NULL, NULL,
&res->id.idmap_id_u.sid.prefix,
- &res->id.idmap_id_u.sid.rid, req, 1);
- if (rc1 == IDMAP_SUCCESS)
- res->id.idtype =
- is_wuser ? IDMAP_USID : IDMAP_GSID;
- else if (rc1 == IDMAP_ERR_NOTFOUND) {
+ &res->id.idmap_id_u.sid.rid,
+ &res->id.idtype,
+ req, 1);
+ if (rc1 == IDMAP_ERR_NOTFOUND) {
req->direction |= _IDMAP_F_LOOKUP_AD;
state->ad_nqueries++;
} else
@@ -913,7 +910,7 @@ out:
if (res->retcode != IDMAP_SUCCESS &&
res->retcode != IDMAP_ERR_NS_LDAP_BAD_WINNAME &&
!(IDMAP_FATAL_ERROR(res->retcode))) {
- idmap_info_free(&res->info);
+ idmap_how_clear(&res->info.how);
res->retcode = IDMAP_SUCCESS;
}
}
diff --git a/usr/src/cmd/idmap/idmapd/server.c b/usr/src/cmd/idmap/idmapd/server.c
index db5e93c876..94a7cea12a 100644
--- a/usr/src/cmd/idmap/idmapd/server.c
+++ b/usr/src/cmd/idmap/idmapd/server.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -123,10 +122,10 @@ validate_mapped_id_by_name_req(idmap_mapping *req)
{
int e;
- if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req))
+ if (IS_ID_UID(req->id1) || IS_ID_GID(req->id1))
return (IDMAP_SUCCESS);
- if (IS_REQUEST_SID(*req, 1)) {
+ if (IS_ID_SID(req->id1)) {
if (!EMPTY_STRING(req->id1name) &&
u8_validate(req->id1name, strlen(req->id1name),
NULL, U8_VALIDATE_ENTIRE, &e) < 0)
@@ -186,6 +185,9 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
lookup_state_t state;
idmap_retcode retcode;
uint_t i;
+ idmap_mapping *req;
+ idmap_id_res *res;
+ boolean_t any_tracing;
/* Init */
(void) memset(result, 0, sizeof (*result));
@@ -241,28 +243,34 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
/* Init our 'done' flags */
state.sid2pid_done = state.pid2sid_done = TRUE;
+ any_tracing = B_FALSE;
+
/* First stage */
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ req = &batch.idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
+ if (TRACING(req))
+ any_tracing = B_TRUE;
state.curpos = i;
- (void) sanitize_mapping_request(
- &batch.idmap_mapping_batch_val[i]);
- if (IS_BATCH_SID(batch, i)) {
+ (void) sanitize_mapping_request(req);
+ TRACE(req, res, "Start mapping");
+ if (IS_ID_SID(req->id1)) {
retcode = sid2pid_first_pass(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i]);
- } else if (IS_BATCH_UID(batch, i)) {
+ req,
+ res);
+ } else if (IS_ID_UID(req->id1)) {
retcode = pid2sid_first_pass(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i], 1);
- } else if (IS_BATCH_GID(batch, i)) {
+ req,
+ res, 1);
+ } else if (IS_ID_GID(req->id1)) {
retcode = pid2sid_first_pass(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i], 0);
+ req,
+ res, 0);
} else {
- result->ids.ids_val[i].retcode = IDMAP_ERR_IDTYPE;
+ res->retcode = IDMAP_ERR_IDTYPE;
continue;
}
if (IDMAP_FATAL_ERROR(retcode)) {
@@ -288,9 +296,23 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
if (state.nldap_nqueries) {
retcode = nldap_lookup_batch(&state, &batch, result);
if (IDMAP_FATAL_ERROR(retcode)) {
+ TRACE(req, res, "Native LDAP lookup error=%d", retcode);
result->retcode = retcode;
goto out;
}
+ if (any_tracing) {
+ for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ res = &result->ids.ids_val[i];
+ req = &batch.idmap_mapping_batch_val[i];
+ if (IDMAP_ERROR(res->retcode)) {
+ TRACE(req, res,
+ "Native LDAP lookup error=%d",
+ res->retcode);
+ } else {
+ TRACE(req, res, "Native LDAP lookup");
+ }
+ }
+ }
}
/*
@@ -310,9 +332,45 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
if (state.ad_nqueries) {
retcode = ad_lookup_batch(&state, &batch, result);
if (IDMAP_FATAL_ERROR(retcode)) {
+ TRACE(req, res, "AD lookup error=%d", retcode);
result->retcode = retcode;
goto out;
}
+ for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ res = &result->ids.ids_val[i];
+ req = &batch.idmap_mapping_batch_val[i];
+ if (res->retcode == IDMAP_ERR_DOMAIN_NOTFOUND &&
+ req->id1.idmap_id_u.sid.prefix != NULL &&
+ req->id1name != NULL) {
+ /*
+ * If AD lookup failed Domain Not Found but
+ * we have a winname and SID, it means that
+ * - LSA succeeded
+ * - it's a request a cross-forest trust
+ * and
+ * - we were looking for directory-based
+ * mapping information.
+ * In that case, we're OK, just go on.
+ *
+ * If this seems more convoluted than it
+ * should be, it is - really, we probably
+ * shouldn't even be attempting AD lookups
+ * in this situation, but that's a more
+ * intricate cleanup that will have to wait
+ * for later.
+ */
+ res->retcode = IDMAP_SUCCESS;
+ TRACE(req, res,
+ "AD lookup - domain not found (ignored)");
+ continue;
+ }
+ if (res->retcode == IDMAP_SUCCESS)
+ TRACE(req, res, "Found in AD");
+ else if (res->retcode == IDMAP_ERR_NOTFOUND)
+ TRACE(req, res, "Not found in AD");
+ else
+ TRACE(req, res, "AD lookup error");
+ }
}
/*
@@ -324,9 +382,17 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
if (state.nldap_nqueries) {
retcode = nldap_lookup_batch(&state, &batch, result);
if (IDMAP_FATAL_ERROR(retcode)) {
+ TRACE(req, res, "Native LDAP lookup error=%d", retcode);
result->retcode = retcode;
goto out;
}
+ if (any_tracing) {
+ for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ res = &result->ids.ids_val[i];
+ req = &batch.idmap_mapping_batch_val[i];
+ TRACE(req, res, "Native LDAP lookup");
+ }
+ }
}
/* Reset 'done' flags */
@@ -334,22 +400,24 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
/* Second stage */
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ req = &batch.idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
state.curpos = i;
- if (IS_BATCH_SID(batch, i)) {
+ if (IS_ID_SID(req->id1)) {
retcode = sid2pid_second_pass(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i]);
- } else if (IS_BATCH_UID(batch, i)) {
+ req,
+ res);
+ } else if (IS_ID_UID(req->id1)) {
retcode = pid2sid_second_pass(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i], 1);
- } else if (IS_BATCH_GID(batch, i)) {
+ req,
+ res, 1);
+ } else if (IS_ID_GID(req->id1)) {
retcode = pid2sid_second_pass(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i], 0);
+ req,
+ res, 0);
} else {
/* First stage has already set the error */
continue;
@@ -373,18 +441,20 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
goto out;
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ req = &batch.idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
state.curpos = i;
- if (IS_BATCH_SID(batch, i)) {
+ if (IS_ID_SID(req->id1)) {
(void) update_cache_sid2pid(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i]);
- } else if ((IS_BATCH_UID(batch, i)) ||
- (IS_BATCH_GID(batch, i))) {
+ req,
+ res);
+ } else if ((IS_ID_UID(req->id1)) ||
+ (IS_ID_GID(req->id1))) {
(void) update_cache_pid2sid(
&state,
- &batch.idmap_mapping_batch_val[i],
- &result->ids.ids_val[i]);
+ req,
+ res);
}
}
@@ -399,11 +469,36 @@ idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
out:
cleanup_lookup_state(&state);
if (IDMAP_ERROR(result->retcode)) {
+ if (any_tracing) {
+ for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ req = &batch.idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
+ TRACE(req, res,
+ "Failure code %d", result->retcode);
+ }
+ }
xdr_free(xdr_idmap_ids_res, (caddr_t)result);
result->ids.ids_len = 0;
result->ids.ids_val = NULL;
+ } else {
+ if (any_tracing) {
+ for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
+ req = &batch.idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
+ TRACE(req, res, "Done");
+ }
+ }
}
result->retcode = idmap_stat4prot(result->retcode);
+
+ for (i = 0; i < result->ids.ids_len; i++) {
+ req = &batch.idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
+
+ if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO) &&
+ res->retcode == IDMAP_SUCCESS)
+ idmap_how_clear(&res->info.how);
+ }
return (TRUE);
}
@@ -1087,11 +1182,7 @@ idmap_get_mapped_id_by_name_1_svc(idmap_mapping request,
result->retcode = batch_result.ids.ids_val[0].retcode;
- if (map->flag & IDMAP_REQ_FLG_MAPPING_INFO ||
- result->retcode != IDMAP_SUCCESS) {
- (void) idmap_info_mov(&map->info,
- &batch_result.ids.ids_val[0].info);
- }
+ idmap_info_mov(&map->info, &batch_result.ids.ids_val[0].info);
out:
if (IDMAP_FATAL_ERROR(result->retcode)) {
diff --git a/usr/src/cmd/idmap/idmapd/wksids.c b/usr/src/cmd/idmap/idmapd/wksids.c
index 3e2c87eab1..90d749d336 100644
--- a/usr/src/cmd/idmap/idmapd/wksids.c
+++ b/usr/src/cmd/idmap/idmapd/wksids.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -223,7 +222,7 @@ static wksids_table_t wksids[] = {
*/
const
wksids_table_t *
-find_wksid_by_name(const char *name, const char *domain, int type)
+find_wksid_by_name(const char *name, const char *domain, idmap_id_type type)
{
int i;
@@ -286,7 +285,7 @@ find_wksid_by_name(const char *name, const char *domain, int type)
*/
const
wksids_table_t *
-find_wksid_by_sid(const char *sid, int rid, int type)
+find_wksid_by_sid(const char *sid, int rid, idmap_id_type type)
{
int i;
diff --git a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
index 49708383c9..58ebaa2945 100644
--- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
+++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
@@ -19,11 +19,11 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#include <sys/mdb_modapi.h>
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
#include <sys/thread.h>
#include <sys/taskq_impl.h>
#include <smbsrv/smb_vops.h>
@@ -35,16 +35,15 @@
#define ACE_TYPE_ENTRY(_v_) {_v_, #_v_}
#define SMB_COM_ENTRY(_v_, _x_) {#_v_, _x_}
-#define SMB_MDB_MAX_OPTS 10
+#define SMB_MDB_MAX_OPTS 9
#define SMB_OPT_SERVER 0x00000001
-#define SMB_OPT_VFS 0x00000002
-#define SMB_OPT_SESSION 0x00000004
-#define SMB_OPT_REQUEST 0x00000008
-#define SMB_OPT_USER 0x00000010
-#define SMB_OPT_TREE 0x00000020
-#define SMB_OPT_OFILE 0x00000040
-#define SMB_OPT_ODIR 0x00000080
+#define SMB_OPT_SESSION 0x00000002
+#define SMB_OPT_REQUEST 0x00000004
+#define SMB_OPT_USER 0x00000008
+#define SMB_OPT_TREE 0x00000010
+#define SMB_OPT_OFILE 0x00000020
+#define SMB_OPT_ODIR 0x00000040
#define SMB_OPT_WALK 0x00000100
#define SMB_OPT_VERBOSE 0x00000200
#define SMB_OPT_ALL_OBJ 0x000000FF
@@ -78,9 +77,22 @@ typedef struct {
/*
* List of supported options. Ther order has the match the bits SMB_OPT_xxx.
*/
-static const char *smb_opts[SMB_MDB_MAX_OPTS] =
+typedef struct smb_mdb_opts {
+ char *o_name;
+ uint32_t o_value;
+} smb_mdb_opts_t;
+
+static smb_mdb_opts_t smb_opts[SMB_MDB_MAX_OPTS] =
{
- "-s", "-m", "-e", "-r", "-u", "-t", "-f", "-d", "-w", "-v"
+ { "-s", SMB_OPT_SERVER },
+ { "-e", SMB_OPT_SESSION },
+ { "-r", SMB_OPT_REQUEST },
+ { "-u", SMB_OPT_USER },
+ { "-t", SMB_OPT_TREE },
+ { "-f", SMB_OPT_OFILE },
+ { "-d", SMB_OPT_ODIR },
+ { "-w", SMB_OPT_WALK },
+ { "-v", SMB_OPT_VERBOSE }
};
static smb_com_entry_t smb_com[256] =
@@ -346,7 +358,6 @@ static smb_com_entry_t smb_com[256] =
static int smb_dcmd_list(uintptr_t, uint_t, int, const mdb_arg_t *);
static void smb_dcmd_list_help(void);
static int smb_dcmd_server(uintptr_t, uint_t, int, const mdb_arg_t *);
-static int smb_dcmd_vfs(uintptr_t, uint_t, int, const mdb_arg_t *);
static void smb_dcmd_session_help(void);
static int smb_dcmd_session(uintptr_t, uint_t, int, const mdb_arg_t *);
static int smb_dcmd_request(uintptr_t, uint_t, int, const mdb_arg_t *);
@@ -356,12 +367,14 @@ static void smb_dcmd_tree_help(void);
static int smb_dcmd_tree(uintptr_t, uint_t, int, const mdb_arg_t *);
static int smb_dcmd_odir(uintptr_t, uint_t, int, const mdb_arg_t *);
static int smb_dcmd_ofile(uintptr_t, uint_t, int, const mdb_arg_t *);
+static int smb_vfs(uintptr_t, uint_t, int, const mdb_arg_t *);
+static int smb_vfs_walk_init(mdb_walk_state_t *);
+static int smb_vfs_walk_step(mdb_walk_state_t *);
static void smb_node_help(void);
static int smb_node(uintptr_t, uint_t, int, const mdb_arg_t *);
static int smb_node_walk_init(mdb_walk_state_t *);
static int smb_node_walk_step(mdb_walk_state_t *);
static int smb_lock(uintptr_t, uint_t, int, const mdb_arg_t *);
-static int smb_stats(uintptr_t, uint_t, int, const mdb_arg_t *);
static int smb_ace(uintptr_t, uint_t, int, const mdb_arg_t *);
static int smb_ace_walk_init(mdb_walk_state_t *);
static int smb_ace_walk_step(mdb_walk_state_t *);
@@ -375,6 +388,7 @@ static int smb_dcmd_setopt(uint_t, int, mdb_arg_t *);
static int smb_obj_expand(uintptr_t, uint_t, const smb_exp_t *, ulong_t);
static int smb_obj_list(const char *, uint_t, uint_t);
static int smb_worker_findstack(uintptr_t);
+static int smb_stats(uintptr_t, uint_t, int, const mdb_arg_t *);
/*
* MDB module linkage information:
@@ -396,7 +410,7 @@ static const mdb_dcmd_t dcmds[] = {
{ "smbvfs",
"[-v]",
"print smb_vfs information",
- smb_dcmd_vfs },
+ smb_vfs },
{ "smbnode",
"?[-vps]",
"print smb_node_t information",
@@ -431,8 +445,9 @@ static const mdb_dcmd_t dcmds[] = {
"[-v]",
"print smb_odir_t information",
smb_dcmd_ofile },
- { "smbstats", NULL,
- "print all smb dispatched requests statistics", smb_stats },
+ { "smbstat", NULL,
+ "print all smb dispatched requests statistics",
+ smb_stats },
{ "smbace", "[-v]",
"print smb_ace_t information", smb_ace },
{ "smbacl", "[-v]",
@@ -453,6 +468,12 @@ static const mdb_walker_t walkers[] = {
smb_node_walk_step,
NULL,
NULL },
+ { "smbvfs_walker",
+ "walk list of smb_vfs_t structures",
+ smb_vfs_walk_init,
+ smb_vfs_walk_step,
+ NULL,
+ NULL },
{ "smbace_walker",
"walk list of smb_ace_t structures",
smb_ace_walk_init,
@@ -490,7 +511,6 @@ smb_dcmd_list_help(void)
mdb_printf(
"-v\tDisplay verbose information\n"
"-s\tDisplay the list of servers\n"
- "-m\tDisplay the list of shared file systems\n"
"-e\tDisplay the list of sessions\n"
"-r\tDisplay the list of smb requests\n"
"-u\tDisplay the list of users\n"
@@ -569,9 +589,6 @@ static const smb_exp_t smb_server_exp[] =
{ SMB_OPT_ALL_OBJ,
offsetof(smb_server_t, sv_tcp_daemon.ld_session_list.se_act.lst),
"smbsess", "smb_session"},
- { SMB_OPT_ALL_OBJ,
- offsetof(smb_server_t, sv_vfs_list.ll_list),
- "smbvfs", "smb_vfs"},
{ 0, 0, NULL, NULL }
};
@@ -620,20 +637,16 @@ smb_dcmd_server(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
"%<b>%<u>%-?s% "
"%-4s% "
"%-32s% "
- "%-6s% "
- "%-6s% "
- "%-6s%</u>%</b>\n",
- "SERVER", "ZONE", "STATE", "USERS",
- "TREES", "FILES");
+ "%</u>%</b>\n",
+ "SERVER", "ZONE", "STATE");
if (sv->sv_state >= SMB_SERVER_STATE_SENTINEL)
state = "UNKNOWN";
else
state = smb_server_state[sv->sv_state];
- mdb_printf("%-?p %-4d %-32s %-6d %-6d %-6d \n",
- addr, sv->sv_zid, state, sv->sv_open_users,
- sv->sv_open_trees, sv->sv_open_files);
+ mdb_printf("%-?p %-4d %-32s \n",
+ addr, sv->sv_zid, state);
}
}
if (smb_obj_expand(addr, opts, smb_server_exp, indent))
@@ -643,68 +656,6 @@ smb_dcmd_server(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
/*
* *****************************************************************************
- * ******************************** smb_vfs_t **********************************
- * *****************************************************************************
- */
-
-/*
- * ::smbvfs
- *
- * smbvfs dcmd - Prints out smb_vfs structures.
- */
-/*ARGSUSED*/
-static int
-smb_dcmd_vfs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
-
- uint_t opts;
-
- if (smb_dcmd_getopt(&opts, argc, argv))
- return (DCMD_USAGE);
-
- if (!(flags & DCMD_ADDRSPEC)) {
- return (smb_obj_list("smb_vfs", SMB_OPT_VFS, flags));
- }
-
- if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_VFS)) ||
- !(opts & SMB_OPT_WALK)) {
- smb_vfs_t *sf;
- vnode_t *vn;
- char *path;
-
- sf = mdb_alloc(sizeof (*sf), UM_SLEEP | UM_GC);
- if (mdb_vread(sf, sizeof (*sf), addr) == -1) {
- mdb_warn("failed to read smb_vfs at %p", addr);
- return (DCMD_ERR);
- }
- vn = mdb_alloc(sizeof (*vn), UM_SLEEP | UM_GC);
- if (mdb_vread(vn, sizeof (*vn),
- (uintptr_t)sf->sv_rootvp) == -1) {
- mdb_warn("failed to read vnode at %p", sf->sv_rootvp);
- return (DCMD_ERR);
- }
- path = mdb_zalloc(MAXPATHLEN, UM_SLEEP | UM_GC);
- (void) mdb_vread(path, MAXPATHLEN, (uintptr_t)vn->v_path);
-
- if (DCMD_HDRSPEC(flags))
- mdb_printf(
- "%<b>%<u>"
- "%-?s "
- "%-10s "
- "%-16s "
- "%-16s"
- "%-s"
- "%</u>%</b>\n",
- "SMB_VFS", "REFCNT", "VFS", "VNODE", "ROOT");
- mdb_printf(
- "%-?p %-10d %-?p %-?p %-s\n", addr, sf->sv_refcnt,
- sf->sv_vfsp, sf->sv_rootvp, path);
- }
- return (DCMD_OK);
-}
-
-/*
- * *****************************************************************************
* ***************************** smb_session_t *********************************
* *****************************************************************************
*/
@@ -784,7 +735,6 @@ smb_dcmd_session(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_warn("failed to read smb_session at %p", addr);
return (DCMD_ERR);
}
-
if (se->s_state >= SMB_SESSION_STATE_SENTINEL)
state = "INVALID";
else
@@ -812,13 +762,13 @@ smb_dcmd_session(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf(
"%<b>%<u>%-?s "
"%-16s "
- "%-16s%</u>%</b>\n",
+ "%-16s %-16s%</u>%</b>\n",
"SESSION", "CLIENT_IP_ADDR",
- "LOCAL_IP_ADDR");
+ "LOCAL_IP_ADDR", "STATE");
mdb_printf(
- "%-?p %-16I %-16I\n", addr, se->ipaddr.a_ipv4,
- se->local_ipaddr.a_ipv4);
+ "%-?p %-16I %-16I %s\n", addr, se->ipaddr.a_ipv4,
+ se->local_ipaddr.a_ipv4, state);
}
}
if (smb_obj_expand(addr, opts, smb_session_exp, indent))
@@ -846,6 +796,11 @@ static const char *smb_request_state[SMB_REQ_STATE_SENTINEL] =
"CLEANED_UP"
};
+#define SMB_REQUEST_BANNER \
+ "%<b>%<u>%-?s %-?s %-14s %-14s %-16s %-32s%</u>%</b>\n"
+#define SMB_REQUEST_FORMAT \
+ "%-?p %-?p %e %e %-16s %s\n"
+
static int
smb_dcmd_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
@@ -864,12 +819,33 @@ smb_dcmd_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
!(opts & SMB_OPT_WALK)) {
smb_request_t *sr;
const char *state;
+ uint64_t waiting;
+ uint64_t running;
sr = mdb_alloc(sizeof (*sr), UM_SLEEP | UM_GC);
if (mdb_vread(sr, sizeof (*sr), addr) == -1) {
mdb_warn("failed to read smb_request at %p", addr);
return (DCMD_ERR);
}
+ if (sr->sr_magic != SMB_REQ_MAGIC) {
+ mdb_warn("not an smb_request_t (%p)>", addr);
+ return (DCMD_ERR);
+ }
+ waiting = 0;
+ running = 0;
+ if (sr->sr_time_submitted != 0) {
+ if (sr->sr_time_active != 0) {
+ waiting = sr->sr_time_active -
+ sr->sr_time_submitted;
+ running = mdb_gethrtime() -
+ sr->sr_time_active;
+ } else {
+ waiting = mdb_gethrtime() -
+ sr->sr_time_submitted;
+ }
+ }
+ waiting /= NANOSEC;
+ running /= NANOSEC;
if (sr->sr_state >= SMB_REQ_STATE_SENTINEL)
state = "INVALID";
@@ -880,27 +856,48 @@ smb_dcmd_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf(
"%</b>%</u>SMB request information (%p):"
"%</u>%</b>\n\n", addr);
- mdb_printf("First SMB COM: %u (%s)\n",
- sr->first_smb_com,
- smb_com[sr->first_smb_com]);
- mdb_printf("State: %u (%s)\n", sr->sr_state, state);
- mdb_printf("Tree: %u (%p)\n", sr->smb_tid,
- sr->tid_tree);
- mdb_printf("User: %u (%p)\n", sr->smb_uid,
- sr->uid_user);
- mdb_printf("File: %u (%p)\n",
- sr->smb_fid, sr->fid_ofile);
- mdb_printf("PID: %u\n", sr->smb_pid);
- mdb_printf("MID: %u\n\n", sr->smb_mid);
+
+ mdb_printf(
+ "first SMB COM: %u (%s)\n"
+ "current SMB COM: %u (%s)\n"
+ "state: %u (%s)\n"
+ "TID(tree): %u (%p)\n"
+ "UID(user): %u (%p)\n"
+ "FID(file): %u (%p)\n"
+ "PID: %u\n"
+ "MID: %u\n\n"
+ "waiting time: %1.3e\n"
+ "running time: %1.3e",
+ sr->first_smb_com, smb_com[sr->first_smb_com],
+ sr->smb_com, smb_com[sr->smb_com],
+ sr->sr_state, state,
+ sr->smb_tid, sr->tid_tree,
+ sr->smb_uid, sr->uid_user,
+ sr->smb_fid, sr->fid_ofile,
+ sr->smb_pid,
+ sr->smb_mid,
+ waiting,
+ running);
+
smb_worker_findstack((uintptr_t)sr->sr_worker);
} else {
if (DCMD_HDRSPEC(flags))
mdb_printf(
- "%<b>%<u>%-?s %-?s %-16s %s%</u>%</b>\n",
- "ADDR", "Worker", "STATE", "COM");
-
- mdb_printf("%-?p %-?p %-16s %s\n", addr, sr->sr_worker,
- state, smb_com[sr->first_smb_com]);
+ SMB_REQUEST_BANNER,
+ "ADDR",
+ "WORKER",
+ "WAITING(s)",
+ "RUNNING(s)",
+ "STATE",
+ "COMMAND");
+
+ mdb_printf(SMB_REQUEST_FORMAT,
+ addr,
+ sr->sr_worker,
+ waiting,
+ running,
+ state,
+ smb_com[sr->smb_com]);
}
}
return (DCMD_OK);
@@ -972,7 +969,6 @@ smb_dcmd_user(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_warn("failed to read smb_user at %p", addr);
return (DCMD_ERR);
}
-
account = mdb_zalloc(user->u_domain_len + user->u_name_len + 2,
UM_SLEEP | UM_GC);
@@ -1088,7 +1084,6 @@ smb_dcmd_tree(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_warn("failed to read smb_tree at %p", addr);
return (DCMD_ERR);
}
-
if (opts & SMB_OPT_VERBOSE) {
const char *state;
@@ -1162,7 +1157,6 @@ smb_dcmd_odir(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_warn("failed to read smb_odir at %p", addr);
return (DCMD_ERR);
}
-
if (opts & SMB_OPT_VERBOSE) {
const char *state;
@@ -1232,7 +1226,6 @@ smb_dcmd_ofile(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_warn("failed to read smb_ofile at %p", addr);
return (DCMD_ERR);
}
-
if (opts & SMB_OPT_VERBOSE) {
const char *state;
@@ -1271,6 +1264,117 @@ smb_dcmd_ofile(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
/*
* *****************************************************************************
+ * ******************************** smb_vfs_t **********************************
+ * *****************************************************************************
+ */
+
+/*
+ * ::smbvfs
+ *
+ * smbvfs dcmd - Prints out smb_vfs structures.
+ */
+/*ARGSUSED*/
+static int
+smb_vfs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ int verbose = FALSE;
+ smb_vfs_t *sf;
+ vnode_t *vn;
+ char *path;
+
+ if (mdb_getopts(argc, argv,
+ 'v', MDB_OPT_SETBITS, TRUE, &verbose,
+ NULL) != argc)
+ return (DCMD_USAGE);
+
+ /*
+ * If no smb_vfs address was specified on the command line, we can
+ * print out all smb_vfs by invoking the smb_vfs walker, using
+ * this dcmd itself as the callback.
+ */
+ if (!(flags & DCMD_ADDRSPEC)) {
+ if (mdb_walk_dcmd("smbvfs_walker", "smbvfs",
+ argc, argv) == -1) {
+ mdb_warn("failed to walk 'smb_vfs'");
+ return (DCMD_ERR);
+ }
+ return (DCMD_OK);
+ }
+
+ if (DCMD_HDRSPEC(flags)) {
+ mdb_printf(
+ "%<b>%<u>"
+ "%-?s "
+ "%-10s "
+ "%-16s "
+ "%-16s"
+ "%-s"
+ "%</u>%</b>\n",
+ "SMB_VFS", "REFCNT", "VFS", "VNODE", "ROOT");
+ }
+
+ sf = mdb_alloc(sizeof (*sf), UM_SLEEP | UM_GC);
+ if (mdb_vread(sf, sizeof (*sf), addr) == -1) {
+ mdb_warn("failed to read smb_vfs at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ vn = mdb_alloc(sizeof (*vn), UM_SLEEP | UM_GC);
+ if (mdb_vread(vn, sizeof (*vn),
+ (uintptr_t)sf->sv_rootvp) == -1) {
+ mdb_warn("failed to read vnode at %p", sf->sv_rootvp);
+ return (DCMD_ERR);
+ }
+
+ path = mdb_zalloc(MAXPATHLEN, UM_SLEEP | UM_GC);
+ (void) mdb_vread(path, MAXPATHLEN, (uintptr_t)vn->v_path);
+
+ mdb_printf(
+ "%-?p %-10d %-?p %-?p %-s\n", addr, sf->sv_refcnt,
+ sf->sv_vfsp, sf->sv_rootvp, path);
+
+ return (DCMD_OK);
+}
+
+/*
+ * Initialize the smb_vfs_t walker by reading the value of smb_export
+ * in the kernel's symbol table. Only global walk supported.
+ */
+static int
+smb_vfs_walk_init(mdb_walk_state_t *wsp)
+{
+ GElf_Sym sym;
+
+ if (wsp->walk_addr != NULL) {
+ mdb_printf("smb_vfs walk only supports global walks\n");
+ return (WALK_ERR);
+ }
+
+ if (mdb_lookup_by_name("smb_export", &sym) == -1) {
+ mdb_warn("failed to find 'smb_export'");
+ return (WALK_ERR);
+ }
+
+ wsp->walk_addr = (uintptr_t)sym.st_value +
+ offsetof(smb_export_t, e_vfs_list) + offsetof(smb_llist_t, ll_list);
+
+ if (mdb_layered_walk("list", wsp) == -1) {
+ mdb_warn("failed to walk list of VFS");
+ return (WALK_ERR);
+ }
+
+ return (WALK_NEXT);
+}
+
+static int
+smb_vfs_walk_step(mdb_walk_state_t *wsp)
+{
+ return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
+ wsp->walk_cbdata));
+}
+
+/*
+ * *****************************************************************************
* ******************************* smb_node_t **********************************
* *****************************************************************************
*/
@@ -1609,41 +1713,38 @@ smb_lock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
/*
- * ::smb_dispatch_stats
+ * ::smbstat
*
- * smb_dispatch_stats dcmd - Prints all dispatched SMB requests statistics.
+ * Prints SMB requests statistics.
*/
/*ARGSUSED*/
static int
smb_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
- smb_disp_entry_t *disp;
- GElf_Sym sym;
- int nstats = 0, i;
+ smb_server_t *sv;
- if ((flags & DCMD_ADDRSPEC) || argc != 0)
+ if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
- if (mdb_lookup_by_obj(MDB_OBJ_EVERY, "dispatch", &sym)) {
- mdb_warn("failed to find dispatch object");
+ sv = mdb_alloc(sizeof (*sv), UM_SLEEP | UM_GC);
+ if (mdb_vread(sv, sizeof (*sv), addr) == -1) {
+ mdb_warn("failed to read server object at %p", addr);
return (DCMD_ERR);
}
-
- disp = mdb_alloc(sym.st_size, UM_SLEEP | UM_GC);
- if (mdb_vread(disp, sym.st_size, sym.st_value) == -1) {
- mdb_warn("failed to read from dispatch object");
+ if (sv->sv_magic != SMB_SERVER_MAGIC) {
+ mdb_warn("not an smb_server_t (%p)>", addr);
return (DCMD_ERR);
}
+ mdb_printf(
+ "\n%<b> nbt tcp users trees files pipes%</b>\n"
+ "%5d %5d %5d %5d %5d %5d\n",
+ sv->sv_nbt_sess,
+ sv->sv_tcp_sess,
+ sv->sv_users,
+ sv->sv_trees,
+ sv->sv_files,
+ sv->sv_pipes);
- nstats = sym.st_size / sizeof (smb_disp_entry_t);
-
- mdb_printf("All dispatched SMB requests statistics:\n\n");
- for (i = 0; i < nstats; i++) {
- if (disp[i].sdt_function)
- mdb_printf(" %40s\t: %lld\n",
- disp[i].sdt_dispatch_stats.name,
- disp[i].sdt_dispatch_stats.value.ui64);
- }
return (DCMD_OK);
}
@@ -2043,7 +2144,6 @@ smb_dcmd_getopt(uint_t *opts, int argc, const mdb_arg_t *argv)
if (mdb_getopts(argc, argv,
's', MDB_OPT_SETBITS, SMB_OPT_SERVER, opts,
- 'm', MDB_OPT_SETBITS, SMB_OPT_VFS, opts,
'e', MDB_OPT_SETBITS, SMB_OPT_SESSION, opts,
'r', MDB_OPT_SETBITS, SMB_OPT_REQUEST, opts,
'u', MDB_OPT_SETBITS, SMB_OPT_USER, opts,
@@ -2071,17 +2171,15 @@ static int
smb_dcmd_setopt(uint_t opts, int max_argc, mdb_arg_t *argv)
{
int i;
- uint_t mask = 0x00000001;
int argc = 0;
for (i = 0; i < SMB_MDB_MAX_OPTS; i++) {
- if ((opts & mask) && (argc < max_argc)) {
+ if ((opts & smb_opts[i].o_value) && (argc < max_argc)) {
argv->a_type = MDB_TYPE_STRING;
- argv->a_un.a_str = smb_opts[i];
+ argv->a_un.a_str = smb_opts[i].o_name;
argc++;
argv++;
}
- mask = mask << 1;
}
return (argc);
}
diff --git a/usr/src/cmd/smbsrv/dtrace/cifs.d b/usr/src/cmd/smbsrv/dtrace/cifs.d
index 0e902e7604..c9748b4b40 100644
--- a/usr/src/cmd/smbsrv/dtrace/cifs.d
+++ b/usr/src/cmd/smbsrv/dtrace/cifs.d
@@ -20,8 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -69,17 +68,62 @@ sdt:smbsrv::-smb_op*-done
self->status = sr->smb_error.status;
}
+sdt:smbsrv::-smb_op-Negotiate-done
+{
+ sr = (struct smb_request *)arg0;
+ negprot = (smb_arg_negotiate_t *)arg1;
+
+ printf("dialect=%s index=%u caps=0x%08x maxmpx=%u tz=%d time=%u",
+ stringof(negprot->ni_name),
+ negprot->ni_index,
+ negprot->ni_capabilities,
+ negprot->ni_maxmpxcount,
+ negprot->ni_tzcorrection,
+ negprot->ni_servertime.tv_sec);
+
+ printf(" [status=0x%08x (class=%d code=%d)]",
+ sr->smb_error.status,
+ sr->smb_error.errcls, sr->smb_error.errcode);
+
+ self->status = sr->smb_error.status;
+}
+
sdt:smbsrv::-smb_op-SessionSetupX-start
{
sr = (struct smb_request *)arg0;
+ ssetup = (smb_arg_sessionsetup_t *)arg1;
- printf("[%s] %s",
+ printf("[%s] %s %s %s",
(sr->session->s_local_port == 139) ? "NBT" : "TCP",
(sr->session->s_local_port == 139) ?
- stringof(sr->session->workstation) : "");
+ stringof(sr->session->workstation) : "",
+ stringof(ssetup->ssi_domain),
+ stringof(ssetup->ssi_user));
+
+ printf(" maxmpx=%u vc=%u maxbuf=%u",
+ ssetup->ssi_maxmpxcount,
+ sr->session->vcnumber,
+ sr->session->smb_msg_size);
+}
+
+sdt:smbsrv::-smb_op-SessionSetupX-done
+{
+ sr = (struct smb_request *)arg0;
+ ssetup = (smb_arg_sessionsetup_t *)arg1;
+
+ printf("%s/%s: smbuid=%d (%s)",
+ stringof(sr->uid_user->u_domain),
+ stringof(sr->uid_user->u_name),
+ sr->smb_uid,
+ (ssetup->ssi_guest == 0) ? "user" : "guest");
+
+ printf(" [status=0x%08x (class=%d code=%d)]",
+ sr->smb_error.status,
+ sr->smb_error.errcls, sr->smb_error.errcode);
+
+ self->status = sr->smb_error.status;
}
-sdt:smbsrv::-smb_op-SessionSetupX-done,
sdt:smbsrv::-smb_op-LogoffX-start
{
sr = (struct smb_request *)arg0;
@@ -98,7 +142,19 @@ sdt:smbsrv::-smb_op-TreeConnectX-start
stringof(tcon->path));
}
-sdt:smbsrv::-smb_op-TreeConnectX-done,
+sdt:smbsrv::-smb_op-TreeConnectX-done
+{
+ sr = (struct smb_request *)arg0;
+
+ printf("tid %d: %s", sr->smb_tid,
+ (sr->smb_error.status == 0) ?
+ stringof(sr->tid_tree->t_sharename) : "");
+
+ printf(" [status=0x%08x (class=%d code=%d)]",
+ sr->smb_error.status,
+ sr->smb_error.errcls, sr->smb_error.errcode);
+}
+
sdt:smbsrv::-smb_op-TreeDisconnect-start
{
sr = (struct smb_request *)arg0;
@@ -172,8 +228,8 @@ sdt:smbsrv::-smb_op-Rename-start
p = (struct dirop *)arg1;
printf("%s to %s",
- stringof(p->fqi.fq_path.pn_path),
- stringof(p->dst_fqi.fq_path.pn_path));
+ stringof(p->fqi.fq_path.pn_path),
+ stringof(p->dst_fqi.fq_path.pn_path));
}
sdt:smbsrv::-smb_op-CheckDirectory-start,
@@ -192,7 +248,7 @@ smb_dispatch_request:return,
smb_pre_*:return,
smb_com_*:return,
smb_post_*:return,
-smbsr_error:return,
+smbsr_status:return,
smbsr_errno:return
{
}
@@ -207,7 +263,7 @@ smb_post_*:entry
sr->smb_com, sr->smb_uid, sr->smb_tid);
}
-smbsr_error:entry
+smbsr_status:entry
{
printf("status=0x%08x class=%d, code=%d\n", arg1, arg2, arg3);
}
diff --git a/usr/src/cmd/smbsrv/dtrace/msrpc.d b/usr/src/cmd/smbsrv/dtrace/msrpc.d
index 4462934cd6..609140bff3 100644
--- a/usr/src/cmd/smbsrv/dtrace/msrpc.d
+++ b/usr/src/cmd/smbsrv/dtrace/msrpc.d
@@ -19,9 +19,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -150,7 +150,7 @@ smb_com_logoff_andx:return
/*
* Raise error functions (no return).
*/
-smbsr_error:entry
+smbsr_status:entry
{
printf("status=0x%08x class=%d, code=%d", arg1, arg2, arg3);
}
@@ -160,7 +160,7 @@ smbsr_errno:entry
printf("errno=%d", arg1);
}
-smbsr_error:return,
+smbsr_status:return,
smbsr_errno:return
{
}
diff --git a/usr/src/cmd/smbsrv/dtrace/stype.d b/usr/src/cmd/smbsrv/dtrace/stype.d
index bf0d143790..ce157e5877 100755..100644
--- a/usr/src/cmd/smbsrv/dtrace/stype.d
+++ b/usr/src/cmd/smbsrv/dtrace/stype.d
@@ -22,12 +22,9 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "@(#)stype.d 1.4 08/08/07 SMI"
-
#pragma D option flowindent
/*
@@ -53,14 +50,37 @@ END
sdt:smbsrv::-smb_op-SessionSetupX-start
{
sr = (struct smb_request *)arg0;
+ ssetup = (smb_arg_sessionsetup_t *)arg1;
- printf("[%s] %s",
+ printf("[%s] %s %s %s",
(sr->session->s_local_port == 139) ? "NBT" : "TCP",
(sr->session->s_local_port == 139) ?
- stringof(sr->session->workstation) : "");
+ stringof(sr->session->workstation) : "",
+ stringof(ssetup->ssi_domain),
+ stringof(ssetup->ssi_user));
+
+ printf(" maxmpx=%u vc=%u maxbuf=%u",
+ ssetup->ssi_maxmpxcount,
+ sr->session->vcnumber,
+ sr->session->smb_msg_size);
+}
+
+sdt:smbsrv::-smb_op-SessionSetupX-done
+{
+ sr = (struct smb_request *)arg0;
+ ssetup = (smb_arg_sessionsetup_t *)arg1;
+
+ printf("%s/%s: smbuid=%d (%s)",
+ stringof(sr->uid_user->u_domain),
+ stringof(sr->uid_user->u_name),
+ sr->smb_uid,
+ (ssetup->ssi_guest == 0) ? "user" : "guest");
+
+ printf(" [status=0x%08x (class=%d code=%d)]",
+ sr->smb_error.status,
+ sr->smb_error.errcls, sr->smb_error.errcode);
}
-sdt:smbsrv::-smb_op-SessionSetupX-done,
sdt:smbsrv::-smb_op-LogoffX-start
{
sr = (struct smb_request *)arg0;
@@ -79,8 +99,20 @@ sdt:smbsrv::-smb_op-TreeConnectX-start
stringof(tcon->path));
}
-sdt:smbsrv::-smb_op-TreeConnectX-done,
-sdt:smbsrv::-smb_op-TreeDisconnect-done
+sdt:smbsrv::-smb_op-TreeConnectX-done
+{
+ sr = (struct smb_request *)arg0;
+
+ printf("tid %d: %s", sr->smb_tid,
+ (sr->smb_error.status == 0) ?
+ stringof(sr->tid_tree->t_sharename) : "");
+
+ printf(" [status=0x%08x (class=%d code=%d)]",
+ sr->smb_error.status,
+ sr->smb_error.errcls, sr->smb_error.errcode);
+}
+
+sdt:smbsrv::-smb_op-TreeDisconnect-start
{
sr = (struct smb_request *)arg0;
@@ -92,7 +124,7 @@ sdt:smbsrv::-smb_op-TreeDisconnect-done
/*
* Error functions
*/
-smbsr_error:entry
+smbsr_status:entry
{
printf("status=0x%08x class=%d, code=%d", arg1, arg2, arg3);
}
@@ -102,7 +134,7 @@ smbsr_errno:entry
printf("errno=%d", arg1);
}
-smbsr_error:return,
+smbsr_status:return,
smbsr_errno:return
{
}
@@ -119,15 +151,16 @@ smb_tree_get_sharename:entry
printf("uncpath=%s", stringof(arg0));
}
-smb_tree_get_stype:entry
+smb_tree_connect_disk:entry
{
- printf("sharename=%s service=%s", stringof(arg0), stringof(arg1));
+ printf("sharename=%s", stringof(arg1));
+ self->stype = 0;
}
-smb_tree_connect_disk:entry
+smb_tree_connect_printq:entry
{
printf("sharename=%s", stringof(arg1));
- self->stype = 0;
+ self->stype = 1;
}
smb_tree_connect_ipc:entry
@@ -138,7 +171,6 @@ smb_tree_connect_ipc:entry
smb_tree_connect:return,
smb_tree_get_sharename:return,
-smb_tree_get_stype:return,
smb_tree_connect_disk:return,
smb_tree_connect_ipc:return
{
diff --git a/usr/src/cmd/smbsrv/smbadm/smbadm.c b/usr/src/cmd/smbsrv/smbadm/smbadm.c
index ecf0f52615..df7f163599 100644
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -748,14 +747,6 @@ smbadm_group_create(int argc, char **argv)
smbadm_usage(B_FALSE);
}
- if (getgrnam(gname) == NULL) {
- (void) fprintf(stderr,
- gettext("failed to get the Solaris group '%s'\n"), gname);
- (void) fprintf(stderr,
- gettext("use 'groupadd' to add '%s'\n"), gname);
- return (1);
- }
-
status = smb_lgrp_add(gname, desc);
if (status != SMB_LGRP_SUCCESS) {
(void) fprintf(stderr,
@@ -994,14 +985,6 @@ smbadm_group_rename(int argc, char **argv)
smbadm_usage(B_FALSE);
}
- if (getgrnam(ngname) == NULL) {
- (void) fprintf(stderr,
- gettext("failed to get the Solaris group '%s'\n"), ngname);
- (void) fprintf(stderr,
- gettext("use 'groupadd' to add '%s'\n"), ngname);
- return (1);
- }
-
status = smb_lgrp_rename(gname, ngname);
if (status != SMB_LGRP_SUCCESS) {
if (status == SMB_LGRP_EXISTS)
diff --git a/usr/src/cmd/smbsrv/smbd/Makefile b/usr/src/cmd/smbsrv/smbd/Makefile
index dff759c94f..2078b536ad 100644
--- a/usr/src/cmd/smbsrv/smbd/Makefile
+++ b/usr/src/cmd/smbsrv/smbd/Makefile
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
@@ -30,6 +29,7 @@ SRCS= \
smbd_join.c \
smbd_logon.c \
smbd_main.c \
+ smbd_nicmon.c \
smbd_opipe_doorsvc.c \
smbd_share_doorsvc.c \
smbd_vss.c
@@ -51,7 +51,7 @@ $(ROOTVARSMBDLL):= FILEMODE = 0755
include ../Makefile.smbsrv.defs
LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lmlsvc -lmlrpc -lsmbns -lsmb \
- -lzfs -lbsm -lnsl -lumem
+ -lzfs -lbsm -lsocket -lnsl -lscf -lumem
LDFLAGS += -R/usr/lib/smbsrv
ROOTSMBDDIR = $(ROOTLIB)/smbsrv
diff --git a/usr/src/cmd/smbsrv/smbd/server.xml b/usr/src/cmd/smbsrv/smbd/server.xml
index 30bbedd595..e5c45813c6 100644
--- a/usr/src/cmd/smbsrv/smbd/server.xml
+++ b/usr/src/cmd/smbsrv/smbd/server.xml
@@ -21,8 +21,7 @@ information: Portions Copyright [yyyy] [name of copyright owner]
CDDL HEADER END
-Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-Use is subject to license terms.
+Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
@@ -207,6 +206,8 @@ file.
value='false' override='true'/>
<propval name='sv_version' type='astring'
value='5.0' override='true'/>
+ <propval name='dfs_stdroot_num' type='integer'
+ value='0' override='true'/>
</property_group>
<!-- SMB service-specific shares exec configuration defaults -->
diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h
index 23bba19cbb..00fa2f5ca7 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd.h
+++ b/usr/src/cmd/smbsrv/smbd/smbd.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SMBD_H
@@ -43,6 +42,9 @@ int smbd_opipe_start(void);
void smbd_opipe_stop(void);
int smbd_share_start(void);
void smbd_share_stop(void);
+int smbd_nicmon_start(const char *);
+void smbd_nicmon_stop(void);
+int smbd_nicmon_refresh(void);
boolean_t smbd_set_netlogon_cred(void);
int smbd_locate_dc_start(void);
smb_token_t *smbd_user_auth_logon(smb_logon_t *);
@@ -78,8 +80,12 @@ typedef struct smbd {
pthread_t s_nbt_listener_id;
pthread_t s_tcp_listener_id;
boolean_t s_fatal_error;
+ smb_log_hdl_t s_loghd;
} smbd_t;
+#define SMBD_LOGNAME "smbd"
+#define SMBD_LOGSIZE 1024
+
#define SMBD_DOOR_NAMESZ 16
typedef struct smbd_door {
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
index e936029edc..5fb3695a16 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
@@ -90,6 +90,8 @@ static int smbd_dop_ads_find_host(smbd_arg_t *);
static int smbd_dop_quota_query(smbd_arg_t *);
static int smbd_dop_quota_set(smbd_arg_t *);
static int smbd_dop_dfs_get_referrals(smbd_arg_t *);
+static int smbd_dop_shr_hostaccess(smbd_arg_t *);
+static int smbd_dop_shr_exec(smbd_arg_t *);
typedef int (*smbd_dop_t)(smbd_arg_t *);
@@ -114,7 +116,9 @@ smbd_doorop_t smbd_doorops[] = {
{ SMB_DR_ADS_FIND_HOST, smbd_dop_ads_find_host },
{ SMB_DR_QUOTA_QUERY, smbd_dop_quota_query },
{ SMB_DR_QUOTA_SET, smbd_dop_quota_set },
- { SMB_DR_DFS_GET_REFERRALS, smbd_dop_dfs_get_referrals }
+ { SMB_DR_DFS_GET_REFERRALS, smbd_dop_dfs_get_referrals },
+ { SMB_DR_SHR_HOSTACCESS, smbd_dop_shr_hostaccess },
+ { SMB_DR_SHR_EXEC, smbd_dop_shr_exec }
};
static int smbd_ndoorop = (sizeof (smbd_doorops) / sizeof (smbd_doorops[0]));
@@ -952,3 +956,56 @@ smbd_dop_dfs_get_referrals(smbd_arg_t *arg)
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
+
+static int
+smbd_dop_shr_hostaccess(smbd_arg_t *arg)
+{
+ smb_shr_hostaccess_query_t request;
+ uint32_t reply;
+
+ bzero(&request, sizeof (request));
+ bzero(&reply, sizeof (reply));
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ smb_shr_hostaccess_query_xdr, &request) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ reply = smb_shr_hostaccess(&request.shq_ipaddr, request.shq_none,
+ request.shq_ro, request.shq_rw, request.shq_flag);
+
+ arg->rbuf = smb_common_encode(&reply, xdr_uint32_t, &arg->rsize);
+
+ xdr_free(smb_shr_hostaccess_query_xdr, (char *)&request);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_shr_exec(smbd_arg_t *arg)
+{
+ smb_shr_execinfo_t request;
+ int reply;
+
+ bzero(&request, sizeof (request));
+ bzero(&reply, sizeof (reply));
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ smb_shr_execinfo_xdr, &request) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ reply = smb_shr_exec(&request);
+
+ if (reply != 0)
+ syslog(LOG_NOTICE, "Failed to execute %s command",
+ (request.e_type == SMB_EXEC_MAP) ? "map" : "unmap");
+
+ arg->rbuf = smb_common_encode(&reply, xdr_int, &arg->rsize);
+
+ xdr_free(smb_shr_execinfo_xdr, (char *)&request);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_join.c b/usr/src/cmd/smbsrv/smbd/smbd_join.c
index a4b57bbeb5..f0bbf9b18c 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_join.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <syslog.h>
@@ -35,7 +35,6 @@
#include <smbsrv/libsmbns.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/smbinfo.h>
-#include <smbsrv/ntstatus.h>
#include "smbd.h"
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c
index 72c5b110b8..0d1ba63615 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -172,11 +171,13 @@ main(int argc, char *argv[])
(void) sigaction(SIGHUP, &act, NULL);
(void) sigaction(SIGINT, &act, NULL);
(void) sigaction(SIGPIPE, &act, NULL);
+ (void) sigaction(SIGUSR1, &act, NULL);
(void) sigdelset(&set, SIGTERM);
(void) sigdelset(&set, SIGHUP);
(void) sigdelset(&set, SIGINT);
(void) sigdelset(&set, SIGPIPE);
+ (void) sigdelset(&set, SIGUSR1);
if (smbd.s_fg) {
(void) sigdelset(&set, SIGTSTP);
@@ -223,6 +224,10 @@ main(int argc, char *argv[])
(void) pthread_cond_signal(&refresh_cond);
break;
+ case SIGUSR1:
+ smb_log_dumpall();
+ break;
+
default:
/*
* Typically SIGINT or SIGTERM.
@@ -465,10 +470,11 @@ smbd_service_init(void)
return (-1);
}
+ smbd.s_loghd = smb_log_create(SMBD_LOGSIZE, SMBD_LOGNAME);
smb_codepage_init();
- if (smb_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0)
- smbd_report("NIC monitoring failed to start");
+ if (smbd_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0)
+ smbd_report("NIC monitor failed to start");
(void) dyndns_start();
smb_ipc_init();
@@ -583,7 +589,7 @@ smbd_service_fini(void)
smbd_share_stop();
smb_shr_stop();
dyndns_stop();
- smb_nicmon_stop();
+ smbd_nicmon_stop();
smb_ccache_remove(SMB_CCACHE_PATH);
smb_pwd_fini();
smb_domain_fini();
@@ -683,9 +689,8 @@ smbd_refresh_monitor(void *arg)
(void) dyndns_start();
dyndns_clear_zones();
- /* re-initialize NIC table */
- if (smb_nic_init() != SMB_NIC_SUCCESS)
- smbd_report("failed to get NIC information");
+ if (smbd_nicmon_refresh() != 0)
+ smbd_report("NIC monitor refresh failed");
smb_netbios_name_reconfig();
smb_browser_reconfig();
smbd_refresh_dc();
@@ -742,8 +747,8 @@ smbd_refresh_dc(void)
if (smb_getfqdomainname(fqdomain, MAXHOSTNAMELEN))
return;
- if (smb_locate_dc(fqdomain, "", NULL))
- smbd_report("DC discovery failed");
+ if (!smb_locate_dc(fqdomain, "", NULL))
+ smbd_report("DC refresh failed");
}
void
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c
new file mode 100644
index 0000000000..bc6739843c
--- /dev/null
+++ b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c
@@ -0,0 +1,323 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * smbd NIC monitor.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <syslog.h>
+#include <smbsrv/libsmb.h>
+#include "smbd.h"
+
+#define SMBD_NICMON_ENABLE "nicmon_enable"
+#define SMBD_NICMON_THROTTLE 100
+#define SMBD_NICMON_DEBOUNCE 2
+
+extern smbd_t smbd;
+
+static boolean_t smbd_nicmon_enabled = B_TRUE;
+
+/* Use this to stop monitoring */
+static int eventpipe_write = -1;
+
+/* Use this to refresh service instance */
+static char *smbd_nicmon_caller_fmri = NULL;
+
+static void smbd_nicmon_run_check(void);
+static int smbd_nicmon_setup_rtsock(int);
+static int smbd_nicmon_needscan(int);
+static int smbd_nicmon_setup_eventpipe(int *, int *);
+static void *smbd_nicmon_daemon(void *);
+
+/*
+ * Start the nic monitor thread.
+ */
+int
+smbd_nicmon_start(const char *svc_fmri)
+{
+ pthread_t smbd_nicmon_tid;
+ int rc;
+
+ if (smb_nic_init() != SMB_NIC_SUCCESS)
+ return (-1);
+
+ rc = pthread_create(&smbd_nicmon_tid, NULL, smbd_nicmon_daemon, NULL);
+ if (rc != 0)
+ return (-1);
+
+ if (svc_fmri)
+ smbd_nicmon_caller_fmri = (char *)svc_fmri;
+
+ smbd_nicmon_run_check();
+ return (0);
+}
+
+void
+smbd_nicmon_stop(void)
+{
+ uchar_t buf = 1;
+
+ if (eventpipe_write < 0)
+ return;
+
+ (void) write(eventpipe_write, &buf, sizeof (buf));
+ smbd_nicmon_caller_fmri = NULL;
+ smb_nic_fini();
+}
+
+int
+smbd_nicmon_refresh(void)
+{
+ if (smb_nic_init() != SMB_NIC_SUCCESS)
+ return (-1);
+
+ smbd_nicmon_run_check();
+ return (0);
+}
+
+/*
+ * The monitor is enabled unless it is explicitly
+ * disabled by setting smbd/nicmon_enable to false.
+ * smbd/nicmon_enable is not defined by default.
+ */
+static void
+smbd_nicmon_run_check(void)
+{
+ smb_scfhandle_t *hd;
+ uint8_t status;
+ int rc;
+
+ smbd_nicmon_enabled = B_TRUE;
+
+ if ((hd = smb_smf_scf_init(SMBD_FMRI_PREFIX)) == NULL) {
+ smb_log(smbd.s_loghd, LOG_DEBUG,
+ "smbd_nicmon: smb_smf_scf_init failed");
+ return;
+ }
+
+ rc = smb_smf_create_service_pgroup(hd, SMBD_PG_NAME);
+ if (rc != SMBD_SMF_OK) {
+ smb_smf_scf_fini(hd);
+ smb_log(smbd.s_loghd, LOG_DEBUG,
+ "smbd_nicmon: smb_smf_create_service_pgroup failed");
+ return;
+ }
+
+ rc = smb_smf_get_boolean_property(hd, SMBD_NICMON_ENABLE, &status);
+ if (rc == SMBD_SMF_OK && status == 0)
+ smbd_nicmon_enabled = B_FALSE;
+
+ smb_smf_scf_fini(hd);
+}
+
+/*
+ * Setup routing socket for getting RTM messages.
+ */
+static int
+smbd_nicmon_setup_rtsock(int af)
+{
+ int sd;
+ int flags;
+
+ if ((sd = socket(PF_ROUTE, SOCK_RAW, af)) == -1) {
+ smb_log(smbd.s_loghd, LOG_ERR,
+ "smbd_nicmon: routing socket failed: %d", errno);
+ return (-1);
+ }
+
+ if ((flags = fcntl(sd, F_GETFL, 0)) < 0) {
+ smb_log(smbd.s_loghd, LOG_ERR,
+ "smbd_nicmon: fcntl F_GETFL failed: %d", errno);
+ (void) close(sd);
+ return (-1);
+ }
+
+ if ((fcntl(sd, F_SETFL, flags | O_NONBLOCK)) < 0) {
+ smb_log(smbd.s_loghd, LOG_ERR,
+ "smbd_nicmon: fcntl F_SETFL failed: %d", errno);
+ (void) close(sd);
+ return (-1);
+ }
+
+ return (sd);
+}
+
+static int
+smbd_nicmon_needscan(int sock)
+{
+ static uint32_t throttle;
+ struct rt_msghdr *rtm;
+ int64_t msg[2048 / 8];
+ int need_if_scan = 0;
+ int nbytes;
+
+ /* Read as many messages as possible and try to empty the sockets */
+ for (;;) {
+ nbytes = read(sock, msg, sizeof (msg));
+ if (nbytes <= 0)
+ break;
+
+ rtm = (struct rt_msghdr *)msg;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+
+ if (nbytes < rtm->rtm_msglen) {
+ if ((throttle % SMBD_NICMON_THROTTLE) == 0) {
+ smb_log(smbd.s_loghd, LOG_DEBUG,
+ "smbd_nicmon: short read: %d of %d",
+ nbytes, rtm->rtm_msglen);
+ }
+ ++throttle;
+ continue;
+ }
+
+ switch (rtm->rtm_type) {
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ case RTM_IFINFO:
+ need_if_scan = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return (need_if_scan);
+}
+
+/*
+ * Create pipe for signal delivery and set up signal handlers.
+ */
+static int
+smbd_nicmon_setup_eventpipe(int *read_pipe, int *write_pipe)
+{
+ int fds[2];
+
+ if ((pipe(fds)) < 0) {
+ smb_log(smbd.s_loghd, LOG_ERR,
+ "smbd_nicmon: event pipe failed: %d", errno);
+ return (-1);
+ }
+
+ *read_pipe = fds[0];
+ *write_pipe = fds[1];
+ return (0);
+}
+
+/*
+ * Create the global routing socket to monitor changes in NIC interfaces.
+ * We are only interested in new inerface addition/deletion and changes
+ * in UP/DOWN status.
+ *
+ * Note: only supports AF_INET routing socket. Need to add AF_INET6 to
+ * support IPv6.
+ */
+/*ARGSUSED*/
+static void *
+smbd_nicmon_daemon(void *arg)
+{
+ static uint32_t throttle;
+ static int rtsock_v4;
+ static int eventpipe_read = -1;
+ struct pollfd pollfds[2];
+ int pollfd_num = 2;
+ int i, nic_changed;
+ int rc;
+
+ if ((rtsock_v4 = smbd_nicmon_setup_rtsock(AF_INET)) == -1)
+ return (NULL);
+
+ rc = smbd_nicmon_setup_eventpipe(&eventpipe_read, &eventpipe_write);
+ if (rc != 0)
+ return (NULL);
+
+ /*
+ * Listen for activity on any of the sockets.
+ * The delay before checking the rtsock will hopefully
+ * smooth things out when there is a lot of activity.
+ */
+ for (;;) {
+ errno = 0;
+ nic_changed = 0;
+ pollfds[0].fd = rtsock_v4;
+ pollfds[0].events = POLLIN;
+ pollfds[1].fd = eventpipe_read;
+ pollfds[1].events = POLLIN;
+
+ if (poll(pollfds, pollfd_num, -1) < 0) {
+ if (errno == EINTR)
+ continue;
+ if ((throttle % SMBD_NICMON_THROTTLE) == 0)
+ smb_log(smbd.s_loghd, LOG_DEBUG,
+ "smbd_nicmon: poll failed: %d", errno);
+ ++throttle;
+ break;
+ }
+
+ for (i = 0; i < pollfd_num; i++) {
+ if ((pollfds[i].fd < 0) ||
+ !(pollfds[i].revents & POLLIN))
+ continue;
+ if (pollfds[i].fd == rtsock_v4) {
+ (void) sleep(SMBD_NICMON_DEBOUNCE);
+ nic_changed = smbd_nicmon_needscan(rtsock_v4);
+ }
+ if (pollfds[i].fd == eventpipe_read)
+ goto done;
+ }
+
+ /*
+ * If the monitor is enabled and something has changed,
+ * refresh the registered SMF service.
+ */
+ if (smbd_nicmon_enabled && nic_changed &&
+ smbd_nicmon_caller_fmri) {
+ if (smf_refresh_instance(smbd_nicmon_caller_fmri) != 0)
+ smb_log(smbd.s_loghd, LOG_ERR,
+ "smbd_nicmon: %s refresh failed",
+ smbd_nicmon_caller_fmri);
+ }
+ }
+done:
+ (void) close(rtsock_v4);
+ (void) close(eventpipe_read);
+ (void) close(eventpipe_write);
+ eventpipe_write = -1;
+ return (NULL);
+}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
index 3792e23853..887e8c5b22 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
@@ -49,7 +49,6 @@ static pthread_mutex_t smb_share_dsrv_mtx = PTHREAD_MUTEX_INITIALIZER;
static smbd_door_t smb_share_sdh;
static void smbd_share_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
-static int smbd_share_enum(smb_enumshare_info_t *esi);
/*
* Start the LanMan share door service.
@@ -145,11 +144,7 @@ smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
char *sharename, *sharename2;
smb_share_t lmshr_info;
smb_shrlist_t lmshr_list;
- smb_enumshare_info_t esi;
int offset;
- smb_inaddr_t ipaddr;
- int exec_type;
- smb_execsub_info_t subs;
smbd_door_enter(&smb_share_sdh);
@@ -203,23 +198,6 @@ smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
smb_dr_free_string(sharename2);
break;
- case SMB_SHROP_GETINFO:
- sharename = smb_dr_get_string(dec_ctx);
- (void) smb_dr_get_buf(dec_ctx, (unsigned char *)&ipaddr,
- sizeof (smb_inaddr_t));
- if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
- smb_dr_free_string(sharename);
- goto decode_error;
- }
- rc = smb_shr_get(sharename, &lmshr_info);
- if (rc == NERR_Success)
- smb_shr_hostaccess(&lmshr_info, &ipaddr);
- smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
- smb_dr_put_uint32(enc_ctx, rc);
- smb_dr_put_share(enc_ctx, &lmshr_info);
- smb_dr_free_string(sharename);
- break;
-
case SMB_SHROP_ADD:
smb_dr_get_share(dec_ctx, &lmshr_info);
if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
@@ -254,59 +232,6 @@ smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
sizeof (smb_shrlist_t));
break;
- case SMB_SHROP_ENUM:
- esi.es_bufsize = smb_dr_get_ushort(dec_ctx);
- esi.es_posix_uid = smb_dr_get_uint32(dec_ctx);
- if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
- goto decode_error;
-
- rc = smbd_share_enum(&esi);
-
- smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
- smb_dr_put_uint32(enc_ctx, rc);
- if (rc == NERR_Success) {
- smb_dr_put_ushort(enc_ctx, esi.es_ntotal);
- smb_dr_put_ushort(enc_ctx, esi.es_nsent);
- smb_dr_put_ushort(enc_ctx, esi.es_datasize);
- smb_dr_put_buf(enc_ctx,
- (unsigned char *)esi.es_buf, esi.es_bufsize);
- free(esi.es_buf);
- }
- break;
-
- case SMB_SHROP_EXEC:
- sharename = smb_dr_get_string(dec_ctx);
- subs.e_winname = smb_dr_get_string(dec_ctx);
- subs.e_userdom = smb_dr_get_string(dec_ctx);
- (void) smb_dr_get_buf(dec_ctx,
- (unsigned char *)&subs.e_srv_ipaddr, sizeof (smb_inaddr_t));
- (void) smb_dr_get_buf(dec_ctx,
- (unsigned char *)&subs.e_cli_ipaddr, sizeof (smb_inaddr_t));
- subs.e_cli_netbiosname = smb_dr_get_string(dec_ctx);
- subs.e_uid = smb_dr_get_int32(dec_ctx);
- exec_type = smb_dr_get_int32(dec_ctx);
- if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
- smb_dr_free_string(sharename);
- smb_dr_free_string(subs.e_winname);
- smb_dr_free_string(subs.e_userdom);
- smb_dr_free_string(subs.e_cli_netbiosname);
- goto decode_error;
- }
-
- rc = smb_shr_exec(sharename, &subs, exec_type);
-
- if (rc != 0)
- syslog(LOG_NOTICE, "Failed to execute %s command",
- (exec_type == SMB_SHR_UNMAP) ? "unmap" : "map");
-
- smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
- smb_dr_put_uint32(enc_ctx, rc);
- smb_dr_free_string(sharename);
- smb_dr_free_string(subs.e_winname);
- smb_dr_free_string(subs.e_userdom);
- smb_dr_free_string(subs.e_cli_netbiosname);
- break;
-
default:
dec_status = smb_dr_decode_finish(dec_ctx);
goto decode_error;
@@ -328,109 +253,3 @@ decode_error:
(void) smb_dr_encode_finish(enc_ctx, &used);
smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
}
-
-/*
- * This function builds a response for a NetShareEnum RAP request which
- * originates from smbsrv kernel module. A response buffer is allocated
- * with the specified size in esi->es_bufsize. List of shares is scanned
- * twice. In the first round the total number of shares which their OEM
- * name is shorter than 13 chars (esi->es_ntotal) and also the number of
- * shares that fit in the given buffer are calculated. In the second
- * round the shares data are encoded in the buffer.
- *
- * The data associated with each share has two parts, a fixed size part and
- * a variable size part which is share's comment. The outline of the response
- * buffer is so that fixed part for all the shares will appear first and follows
- * with the comments for all those shares and that's why the data cannot be
- * encoded in one round without unnecessarily complicating the code.
- */
-static int
-smbd_share_enum(smb_enumshare_info_t *esi)
-{
- smb_shriter_t shi;
- smb_share_t *si;
- int remained;
- uint16_t infolen = 0;
- uint16_t cmntlen = 0;
- uint16_t sharelen;
- uint16_t clen;
- uint32_t cmnt_offs;
- smb_msgbuf_t info_mb;
- smb_msgbuf_t cmnt_mb;
- boolean_t autohome_added = B_FALSE;
-
- esi->es_ntotal = esi->es_nsent = 0;
-
- if ((esi->es_buf = malloc(esi->es_bufsize)) == NULL)
- return (NERR_InternalError);
-
- bzero(esi->es_buf, esi->es_bufsize);
- remained = esi->es_bufsize;
-
- /* Do the necessary calculations in the first round */
- smb_shr_iterinit(&shi);
-
- while ((si = smb_shr_iterate(&shi)) != NULL) {
- if (si->shr_flags & SMB_SHRF_LONGNAME)
- continue;
-
- if ((si->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
- if (esi->es_posix_uid == si->shr_uid)
- autohome_added = B_TRUE;
- else
- continue;
- }
-
- esi->es_ntotal++;
-
- if (remained <= 0)
- continue;
-
- clen = strlen(si->shr_cmnt) + 1;
- sharelen = SHARE_INFO_1_SIZE + clen;
-
- if (sharelen <= remained) {
- infolen += SHARE_INFO_1_SIZE;
- cmntlen += clen;
- }
-
- remained -= sharelen;
- }
-
- esi->es_datasize = infolen + cmntlen;
-
- smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0);
- smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0);
- cmnt_offs = infolen;
-
- /* Encode the data in the second round */
- smb_shr_iterinit(&shi);
- autohome_added = B_FALSE;
-
- while ((si = smb_shr_iterate(&shi)) != NULL) {
- if (si->shr_flags & SMB_SHRF_LONGNAME)
- continue;
-
- if ((si->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
- if (esi->es_posix_uid == si->shr_uid)
- autohome_added = B_TRUE;
- else
- continue;
- }
-
- if (smb_msgbuf_encode(&info_mb, "13c.wl",
- si->shr_oemname, si->shr_type, cmnt_offs) < 0)
- break;
-
- if (smb_msgbuf_encode(&cmnt_mb, "s", si->shr_cmnt) < 0)
- break;
-
- cmnt_offs += strlen(si->shr_cmnt) + 1;
- esi->es_nsent++;
- }
-
- smb_msgbuf_term(&info_mb);
- smb_msgbuf_term(&cmnt_mb);
-
- return (NERR_Success);
-}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_vss.c b/usr/src/cmd/smbsrv/smbd/smbd_vss.c
index c49c541a74..411037b8e6 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_vss.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_vss.c
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <synch.h>
@@ -35,7 +35,6 @@
#include <smbsrv/libsmbns.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/smbinfo.h>
-#include <smbsrv/ntstatus.h>
#include "smbd.h"
/*
diff --git a/usr/src/cmd/smbsrv/smbstat/Makefile b/usr/src/cmd/smbsrv/smbstat/Makefile
index c44c076464..64268ccf70 100644
--- a/usr/src/cmd/smbsrv/smbstat/Makefile
+++ b/usr/src/cmd/smbsrv/smbstat/Makefile
@@ -19,10 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG= smbstat
@@ -34,6 +31,6 @@ OBJS= $(SRCS:%.c=%.o)
include ../Makefile.smbsrv.defs
-LDLIBS += -lkstat
+LDLIBS += -lkstat -lm -lumem
include ../Makefile.smbsrv.targ
include ../../Makefile.targ
diff --git a/usr/src/cmd/smbsrv/smbstat/smbstat.c b/usr/src/cmd/smbsrv/smbstat/smbstat.c
index aad8655318..de3773d247 100644
--- a/usr/src/cmd/smbsrv/smbstat/smbstat.c
+++ b/usr/src/cmd/smbsrv/smbstat/smbstat.c
@@ -20,17 +20,74 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* smbstat: Server Message Block File System statistics
+ *
+ * The statistics this CLI displays come from two sources:
+ *
+ * 1) The kernel module 'smbsrv'.
+ * 2) The SMB workers task queue statistics the task queue manager of Solaris
+ * maintains.
+ *
+ * The flow of the code is the following:
+ *
+ *
+ * +----------------+
+ * | Initialization |
+ * +----------------+
+ * |
+ * |
+ * v
+ * +--------------------------*
+ * | Take a snapshot the data | <--------+
+ * +--------------------------+ |
+ * | |
+ * | |
+ * v |
+ * +----------------------+ |
+ * | Process the snapshot | |
+ * +----------------------+ |
+ * | |
+ * | |
+ * v |
+ * +------------------------------------+ |
+ * | Print the result of the processing | |
+ * +------------------------------------+ |
+ * | |
+ * | |
+ * v |
+ * Yes --------------- |
+ * +------------ < interval == 0 ? > |
+ * | --------------- |
+ * | | |
+ * | | No |
+ * | v |
+ * | +------------------------+ |
+ * | | Sleep for the duration | ----------+
+ * | | of the interval. |
+ * | +------------------------+
+ * |
+ * +---------------------+
+ * |
+ * v
+ *
+ * Exit
+ *
+ * There are two sets of snapshots. One set for the smbsrv module and the other
+ * for the task queue (SMB workers). Each set contains 2 snapshots. One is
+ * labeled 'current' the other one 'previous'. Their role changes after each
+ * snapshot. The 'current' becomes 'previous' and vice versa.
+ * The first snapshot taken is compared against the data gathered since the
+ * smbsrv module was loaded. Subsequent snapshots will be compared against the
+ * previous snapshot.
*/
+
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <kstat.h>
#include <stdarg.h>
#include <errno.h>
@@ -39,32 +96,216 @@
#include <utility.h>
#include <libintl.h>
#include <zone.h>
+#include <termios.h>
+#include <stropts.h>
+#include <math.h>
+#include <umem.h>
+#include <locale.h>
#include <smbsrv/smb_kstat.h>
-static kstat_ctl_t *kc; /* libkstat cookie */
-static kstat_t *smb_server;
-static kstat_t *smb_cmds;
+#if !defined(TEXT_DOMAIN)
+#define TEXT_DOMAIN "SYS_TEST"
+#endif /* TEXT_DOMAIN */
+
+#define SMBSTAT_ID_NO_CPU -1
+#define SMBSTAT_SNAPSHOT_COUNT 2 /* Must be a power of 2 */
+#define SMBSTAT_SNAPSHOT_MASK (SMBSTAT_SNAPSHOT_COUNT - 1)
+
+#define SMBSTAT_HELP \
+ "Usage: smbstat [-acnrtuz] [interval]\n" \
+ " -c: display counters\n" \
+ " -t: display throughput\n" \
+ " -u: display utilization\n" \
+ " -r: display requests\n" \
+ " -a: all the requests (supported and unsupported)\n" \
+ " -z: skip the requests not received\n" \
+ " -n: display in alphabetic order\n" \
+ " interval: refresh cycle in seconds\n"
+
+#define SMBSRV_COUNTERS_BANNER "\n nbt tcp users trees files pipes\n"
+#define SMBSRV_COUNTERS_FORMAT "%5d %5d %5d %5d %5d %5d\n"
+
+#define SMBSRV_THROUGHPUT_BANNER \
+ "\nrbytes/s tbytes/s reqs/s reads/s writes/s\n"
+#define SMBSRV_THROUGHPUT_FORMAT \
+ "%1.3e %1.3e %1.3e %1.3e %1.3e\n"
+
+#define SMBSRV_UTILIZATION_BANNER \
+ "\n wcnt rcnt wtime rtime" \
+ " w%% r%% u%% sat usr%% sys%% idle%%\n"
+#define SMBSRV_UTILIZATION_FORMAT \
+ "%1.3e %1.3e %1.3e %1.3e %3.0f %3.0f %3.0f %s " \
+ "%3.0f %3.0f %3.0f\n"
+
+#define SMBSRV_REQUESTS_BANNER \
+ "\n%30s code %% rbytes/s tbytes/s req/s rt-mean" \
+ " rt-stddev\n"
+#define SMBSRV_REQUESTS_FORMAT \
+ "%30s %02X %3.0f %1.3e %1.3e %1.3e %1.3e %1.3e\n"
+
+typedef enum {
+ CPU_TICKS_IDLE = 0,
+ CPU_TICKS_USER,
+ CPU_TICKS_KERNEL,
+ CPU_TICKS_SENTINEL
+} cpu_state_idx_t;
+
+typedef struct smbstat_cpu_snapshot {
+ processorid_t cs_id;
+ int cs_state;
+ uint64_t cs_ticks[CPU_TICKS_SENTINEL];
+} smbstat_cpu_snapshot_t;
+
+typedef struct smbstat_srv_snapshot {
+ hrtime_t ss_snaptime;
+ smbsrv_kstats_t ss_data;
+} smbstat_srv_snapshot_t;
+
+typedef struct smbstat_wrk_snapshot {
+ uint64_t ws_maxthreads;
+ uint64_t ws_bnalloc;
+} smbstat_wrk_snapshot_t;
+
+typedef struct smbstat_req_info {
+ char ri_name[KSTAT_STRLEN];
+ int ri_opcode;
+ double ri_pct;
+ double ri_tbs;
+ double ri_rbs;
+ double ri_rqs;
+ double ri_stddev;
+ double ri_mean;
+} smbstat_req_info_t;
+
+typedef struct smbstat_srv_info {
+ double si_hretime;
+ double si_etime;
+ double si_total_nreqs;
+ /*
+ * Counters
+ */
+ uint32_t si_nbt_sess; /* NBT sessions */
+ uint32_t si_tcp_sess; /* TCP sessions */
+ uint32_t si_users; /* Users logged in */
+ uint32_t si_trees; /* Trees connected */
+ uint32_t si_files; /* Open files */
+ uint32_t si_pipes; /* Open pipes */
+ /*
+ * Throughput of the server
+ */
+ double si_tbs; /* Bytes transmitted / second */
+ double si_rbs; /* Bytes received / second */
+ double si_rqs; /* Requests treated / second */
+ double si_rds; /* Reads treated / second */
+ double si_wrs; /* Writes treated / second */
+ /*
+ * Utilization of the server
+ */
+ double si_wpct; /* */
+ double si_rpct; /* */
+ double si_upct; /* Utilization in % */
+ double si_avw; /* Average number of requests waiting */
+ double si_avr; /* Average number of requests running */
+ double si_wserv; /* Average waiting time */
+ double si_rserv; /* Average running time */
+ boolean_t si_sat;
+ double si_ticks[CPU_TICKS_SENTINEL];
+ /*
+ * Latency & Throughput per request
+ */
+ smbstat_req_info_t si_reqs[SMB_COM_NUM];
+} smbstat_srv_info_t;
-static int get_smbinfo_stat(void);
-static int get_smbdispatch_stat(void);
static void smbstat_init(void);
static void smbstat_fini(void);
-static void smbstat_smb_server_print();
-static void smbstat_smb_cmds_print();
-static void smbstat_print(const char *, kstat_t *, int);
-static int smbstat_width(kstat_t *, int);
+static void smbstat_kstat_snapshot(void);
+static void smbstat_kstat_process(void);
+static void smbstat_kstat_print(void);
+
+static void smbstat_print_counters(void);
+static void smbstat_print_throughput(void);
+static void smbstat_print_utilization(void);
+static void smbstat_print_requests(void);
+
+static void smbstat_cpu_init(void);
+static void smbstat_cpu_fini(void);
+static smbstat_cpu_snapshot_t *smbstat_cpu_current_snapshot(void);
+static smbstat_cpu_snapshot_t *smbstat_cpu_previous_snapshot(void);
+static void smbstat_cpu_snapshot(void);
+static void smbstat_cpu_process(void);
+
+static void smbstat_wrk_init(void);
+static void smbstat_wrk_fini(void);
+static void smbstat_wrk_snapshot(void);
+static void smbstat_wrk_process(void);
+static smbstat_wrk_snapshot_t *smbstat_wrk_current_snapshot(void);
+
+static void smbstat_srv_init(void);
+static void smbstat_srv_fini(void);
+static void smbstat_srv_snapshot(void);
+static void smbstat_srv_process(void);
+static void smbstat_srv_process_counters(smbstat_srv_snapshot_t *);
+static void smbstat_srv_process_throughput(smbstat_srv_snapshot_t *,
+ smbstat_srv_snapshot_t *);
+static void smbstat_srv_process_utilization(smbstat_srv_snapshot_t *,
+ smbstat_srv_snapshot_t *);
+static void smbstat_srv_process_requests(smbstat_srv_snapshot_t *,
+ smbstat_srv_snapshot_t *);
+static smbstat_srv_snapshot_t *smbstat_srv_current_snapshot(void);
+static smbstat_srv_snapshot_t *smbstat_srv_previous_snapshot(void);
+
+static void *smbstat_zalloc(size_t);
+static void smbstat_free(void *, size_t);
static void smbstat_fail(int, char *, ...);
-static kid_t smbstat_kstat_read(kstat_ctl_t *, kstat_t *, void *);
-static void smbstat_usage(void);
+static void smbstat_snapshot_inc_idx(void);
+static void smbstat_usage(FILE *, int);
+static uint_t smbstat_strtoi(char const *, char *);
+static double smbstat_hrtime_delta(hrtime_t, hrtime_t);
+static double smbstat_sub_64(uint64_t, uint64_t);
+static void smbstat_req_order(void);
+static double smbstat_zero(double);
+static void smbstat_termio_init(void);
+
+#pragma does_not_return(smbstat_fail, smbstat_usage)
+
+static char *smbstat_cpu_states[CPU_TICKS_SENTINEL] = {
+ "cpu_ticks_idle",
+ "cpu_ticks_user",
+ "cpu_ticks_kernel"
+};
-#define MAX_COLUMNS 80
+static boolean_t smbstat_opt_a = B_FALSE; /* all */
+static boolean_t smbstat_opt_c = B_FALSE; /* counters */
+static boolean_t smbstat_opt_n = B_FALSE; /* by name */
+static boolean_t smbstat_opt_u = B_FALSE; /* utilization */
+static boolean_t smbstat_opt_t = B_FALSE; /* throughput */
+static boolean_t smbstat_opt_r = B_FALSE; /* requests */
+static boolean_t smbstat_opt_z = B_FALSE; /* non-zero requests */
+static uint_t smbstat_interval = 0;
+static long smbstat_nrcpus = 0;
+static kstat_ctl_t *smbstat_ksc = NULL;
+static kstat_t *smbstat_srv_ksp = NULL;
+static kstat_t *smbstat_wrk_ksp = NULL;
+static struct winsize smbstat_ws;
+static uint16_t smbstat_rows = 0;
+
+static int smbstat_snapshot_idx = 0;
+static smbstat_cpu_snapshot_t *smbstat_cpu_snapshots[SMBSTAT_SNAPSHOT_COUNT];
+static smbstat_srv_snapshot_t smbstat_srv_snapshots[SMBSTAT_SNAPSHOT_COUNT];
+static smbstat_wrk_snapshot_t smbstat_wrk_snapshots[SMBSTAT_SNAPSHOT_COUNT];
+static smbstat_srv_info_t smbstat_srv_info;
+
+/*
+ * main
+ */
int
main(int argc, char *argv[])
{
- int c;
- int iflag = 0; /* smb_server stats */
- int dflag = 0; /* smb_cmds_all stats */
+ int c;
+
+ (void) setlocale(LC_ALL, "");
+ (void) textdomain(TEXT_DOMAIN);
if (getzoneid() != GLOBAL_ZONEID) {
(void) fprintf(stderr,
@@ -80,192 +321,781 @@ main(int argc, char *argv[])
return (0);
}
- while ((c = getopt(argc, argv, "id")) != EOF) {
+ while ((c = getopt(argc, argv, "achnrtuz")) != EOF) {
switch (c) {
- case 'i':
- iflag++;
+ case 'a':
+ smbstat_opt_a = B_TRUE;
break;
- case 'd':
- dflag++;
+ case 'n':
+ smbstat_opt_n = B_TRUE;
break;
- case '?':
+ case 'u':
+ smbstat_opt_u = B_TRUE;
+ break;
+ case 'c':
+ smbstat_opt_c = B_TRUE;
+ break;
+ case 'r':
+ smbstat_opt_r = B_TRUE;
+ break;
+ case 't':
+ smbstat_opt_t = B_TRUE;
+ break;
+ case 'z':
+ smbstat_opt_z = B_TRUE;
+ break;
+ case 'h':
+ smbstat_usage(stdout, 0);
default:
- smbstat_usage();
+ smbstat_usage(stderr, 1);
}
}
- if ((argc - optind) > 0) {
- smbstat_usage();
+ if (!smbstat_opt_u &&
+ !smbstat_opt_c &&
+ !smbstat_opt_r &&
+ !smbstat_opt_t) {
+ /* Default options when none is specified. */
+ smbstat_opt_u = B_TRUE;
+ smbstat_opt_t = B_TRUE;
}
- smbstat_init();
-
- if (iflag) {
- smbstat_smb_server_print();
- } else if (dflag) {
- smbstat_smb_cmds_print();
- } else {
- smbstat_smb_server_print();
- smbstat_smb_cmds_print();
+ if (optind < argc) {
+ smbstat_interval =
+ smbstat_strtoi(argv[optind], "invalid count");
+ optind++;
}
- smbstat_fini();
+ if ((argc - optind) > 1)
+ smbstat_usage(stderr, 1);
+
+ (void) atexit(smbstat_fini);
+ smbstat_init();
+ for (;;) {
+ smbstat_kstat_snapshot();
+ smbstat_kstat_process();
+ smbstat_kstat_print();
+ if (smbstat_interval == 0)
+ break;
+ (void) sleep(smbstat_interval);
+ smbstat_snapshot_inc_idx();
+ }
return (0);
}
+/*
+ * smbstat_init
+ *
+ * Global initialization.
+ */
+static void
+smbstat_init(void)
+{
+ if ((smbstat_ksc = kstat_open()) == NULL)
+ smbstat_fail(1, gettext("kstat_open(): can't open /dev/kstat"));
-static int
-get_smbinfo_stat(void)
+ smbstat_cpu_init();
+ smbstat_srv_init();
+ smbstat_wrk_init();
+ smbstat_req_order();
+}
+
+/*
+ * smbstat_fini
+ *
+ * Releases the resources smbstat_init() allocated.
+ */
+static void
+smbstat_fini(void)
{
- (void) smbstat_kstat_read(kc, smb_server, NULL);
- return (smbstat_width(smb_server, 0));
+ smbstat_wrk_fini();
+ smbstat_srv_fini();
+ smbstat_cpu_fini();
+ (void) kstat_close(smbstat_ksc);
}
-static int
-get_smbdispatch_stat(void)
+/*
+ * smbstat_kstat_snapshot
+ *
+ * Takes a snapshot of the data.
+ */
+static void
+smbstat_kstat_snapshot(void)
+{
+ smbstat_cpu_snapshot();
+ smbstat_srv_snapshot();
+ smbstat_wrk_snapshot();
+}
+
+/*
+ * smbstat_kstat_process
+ */
+static void
+smbstat_kstat_process(void)
+{
+ smbstat_cpu_process();
+ smbstat_srv_process();
+ smbstat_wrk_process();
+}
+
+/*
+ * smbstat_kstat_print
+ *
+ * Print the data processed.
+ */
+static void
+smbstat_kstat_print(void)
+{
+ smbstat_termio_init();
+ smbstat_print_counters();
+ smbstat_print_throughput();
+ smbstat_print_utilization();
+ smbstat_print_requests();
+}
+
+/*
+ * smbstat_print_counters
+ *
+ * Displays the SMB server counters (session, users...).
+ */
+static void
+smbstat_print_counters(void)
+{
+ if (!smbstat_opt_c)
+ return;
+
+ if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_t ||
+ (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) {
+ (void) printf(SMBSRV_COUNTERS_BANNER);
+ smbstat_rows = 1;
+ }
+
+ (void) printf(SMBSRV_COUNTERS_FORMAT,
+ smbstat_srv_info.si_nbt_sess,
+ smbstat_srv_info.si_tcp_sess,
+ smbstat_srv_info.si_users,
+ smbstat_srv_info.si_trees,
+ smbstat_srv_info.si_files,
+ smbstat_srv_info.si_pipes);
+
+ ++smbstat_rows;
+}
+/*
+ * smbstat_print_throughput
+ *
+ * Formats the SMB server throughput output.
+ */
+static void
+smbstat_print_throughput(void)
+{
+ if (!smbstat_opt_t)
+ return;
+
+ if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_c ||
+ (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) {
+ (void) printf(SMBSRV_THROUGHPUT_BANNER);
+ smbstat_rows = 1;
+ }
+ (void) printf(SMBSRV_THROUGHPUT_FORMAT,
+ smbstat_zero(smbstat_srv_info.si_rbs),
+ smbstat_zero(smbstat_srv_info.si_tbs),
+ smbstat_zero(smbstat_srv_info.si_rqs),
+ smbstat_zero(smbstat_srv_info.si_rds),
+ smbstat_zero(smbstat_srv_info.si_wrs));
+
+ ++smbstat_rows;
+}
+
+/*
+ * smbstat_print_utilization
+ */
+static void
+smbstat_print_utilization(void)
{
- (void) smbstat_kstat_read(kc, smb_cmds, NULL);
- return (smbstat_width(smb_cmds, 0));
+ char *sat;
+ if (!smbstat_opt_u)
+ return;
+
+ if (smbstat_opt_t || smbstat_opt_r || smbstat_opt_c ||
+ (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) {
+ (void) printf(SMBSRV_UTILIZATION_BANNER);
+ smbstat_rows = 1;
+ }
+
+ if (smbstat_srv_info.si_sat)
+ sat = "yes";
+ else
+ sat = "no ";
+
+ (void) printf(SMBSRV_UTILIZATION_FORMAT,
+ smbstat_srv_info.si_avw,
+ smbstat_srv_info.si_avr,
+ smbstat_srv_info.si_wserv,
+ smbstat_srv_info.si_rserv,
+ smbstat_zero(smbstat_srv_info.si_wpct),
+ smbstat_zero(smbstat_srv_info.si_rpct),
+ smbstat_zero(smbstat_srv_info.si_upct),
+ sat,
+ smbstat_srv_info.si_ticks[CPU_TICKS_USER],
+ smbstat_srv_info.si_ticks[CPU_TICKS_KERNEL],
+ smbstat_srv_info.si_ticks[CPU_TICKS_IDLE]);
+
+ ++smbstat_rows;
}
+/*
+ * smbstat_print_requests
+ */
static void
-smbstat_smb_server_print()
+smbstat_print_requests(void)
{
- int field_width;
- int i, j, nreq, ncolumns;
- char fixlen[128];
- kstat_named_t *knp;
+ smbstat_req_info_t *prq;
+ int i;
- field_width = get_smbinfo_stat();
- if (field_width == 0)
+ if (!smbstat_opt_r)
return;
- (void) printf("%s\n", "\nSMB Info:\n");
- ncolumns = (MAX_COLUMNS -1)/field_width;
+ prq = smbstat_srv_info.si_reqs;
+
+ (void) printf(SMBSRV_REQUESTS_BANNER, " ");
- knp = KSTAT_NAMED_PTR(smb_server);
- nreq = smb_server->ks_ndata;
+ for (i = 0; i < SMB_COM_NUM; i++) {
+ if (!smbstat_opt_a &&
+ strncmp(prq[i].ri_name, "Invalid", sizeof ("Invalid")) == 0)
+ continue;
- for (i = 0; i < nreq; i += ncolumns) {
- /* prints out the titles of the columns */
- for (j = i; j < MIN(i + ncolumns, nreq); j++) {
- (void) printf("%-*s", field_width, knp[j].name);
+ if (!smbstat_opt_z || (prq[i].ri_pct != 0)) {
+ (void) printf(SMBSRV_REQUESTS_FORMAT,
+ prq[i].ri_name,
+ prq[i].ri_opcode,
+ smbstat_zero(prq[i].ri_pct),
+ smbstat_zero(prq[i].ri_rbs),
+ smbstat_zero(prq[i].ri_tbs),
+ smbstat_zero(prq[i].ri_rqs),
+ prq[i].ri_mean,
+ prq[i].ri_stddev);
}
- (void) printf("\n");
- /* prints out the stat numbers */
- for (j = i; j < MIN(i + ncolumns, nreq); j++) {
- (void) sprintf(fixlen, "%" PRIu32 " ",
- knp[j].value.ui32);
- (void) printf("%-*s", field_width, fixlen);
+ }
+}
+
+/*
+ * smbstat_cpu_init
+ */
+static void
+smbstat_cpu_init(void)
+{
+ size_t size;
+ int i;
+
+ smbstat_nrcpus = sysconf(_SC_CPUID_MAX) + 1;
+ size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t);
+
+ for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++)
+ smbstat_cpu_snapshots[i] = smbstat_zalloc(size);
+}
+
+/*
+ * smbstat_cpu_fini
+ */
+static void
+smbstat_cpu_fini(void)
+{
+ size_t size;
+ int i;
+
+ size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t);
+
+ for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++)
+ smbstat_free(smbstat_cpu_snapshots[i], size);
+}
+
+/*
+ * smbstat_cpu_current_snapshot
+ */
+static smbstat_cpu_snapshot_t *
+smbstat_cpu_current_snapshot(void)
+{
+ return (smbstat_cpu_snapshots[smbstat_snapshot_idx]);
+}
+
+/*
+ * smbstat_cpu_previous_snapshot
+ */
+static smbstat_cpu_snapshot_t *
+smbstat_cpu_previous_snapshot(void)
+{
+ int idx;
+
+ idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK;
+ return (smbstat_cpu_snapshots[idx]);
+}
+
+/*
+ * smbstat_cpu_snapshot
+ */
+static void
+smbstat_cpu_snapshot(void)
+{
+ kstat_t *ksp;
+ kstat_named_t *ksn;
+ smbstat_cpu_snapshot_t *curr;
+ long i;
+ int j;
+
+ curr = smbstat_cpu_current_snapshot();
+
+ for (i = 0; i < smbstat_nrcpus; i++, curr++) {
+ curr->cs_id = SMBSTAT_ID_NO_CPU;
+ curr->cs_state = p_online(i, P_STATUS);
+ /* If no valid CPU is present, move on to the next one */
+ if (curr->cs_state == -1)
+ continue;
+
+ curr->cs_id = i;
+
+ ksp = kstat_lookup(smbstat_ksc, "cpu", i, "sys");
+ if (ksp == NULL)
+ smbstat_fail(1,
+ gettext("kstat_lookup('cpu sys %d') failed"), i);
+
+ if (kstat_read(smbstat_ksc, ksp, NULL) == -1)
+ smbstat_fail(1,
+ gettext("kstat_read('cpu sys %d') failed"), i);
+
+ for (j = 0; j < CPU_TICKS_SENTINEL; j++) {
+ ksn = kstat_data_lookup(ksp, smbstat_cpu_states[j]);
+ if (ksn == NULL)
+ smbstat_fail(1,
+ gettext("kstat_data_lookup('%s') failed"),
+ smbstat_cpu_states[j]);
+ curr->cs_ticks[j] = ksn->value.ui64;
}
- (void) printf("\n");
}
}
+/*
+ * smbstat_cpu_process
+ */
static void
-smbstat_smb_cmds_print()
+smbstat_cpu_process(void)
{
- int field_width;
+ smbstat_cpu_snapshot_t *curr, *prev;
+ double total_ticks;
+ double agg_ticks[CPU_TICKS_SENTINEL];
+ int i, j;
- field_width = get_smbdispatch_stat();
- if (field_width == 0)
- return;
+ curr = smbstat_cpu_current_snapshot();
+ prev = smbstat_cpu_previous_snapshot();
+ bzero(agg_ticks, sizeof (agg_ticks));
+ total_ticks = 0;
- smbstat_print(gettext("\nAll dispatched SMB requests statistics:\n"),
- smb_cmds, field_width);
+ for (i = 0; i < smbstat_nrcpus; i++, curr++, prev++) {
+ for (j = 0; j < CPU_TICKS_SENTINEL; j++) {
+ agg_ticks[j] += smbstat_sub_64(curr->cs_ticks[j],
+ prev->cs_ticks[j]);
+ total_ticks += smbstat_sub_64(curr->cs_ticks[j],
+ prev->cs_ticks[j]);
+ }
+ }
+
+ for (j = 0; j < CPU_TICKS_SENTINEL; j++)
+ smbstat_srv_info.si_ticks[j] =
+ (agg_ticks[j] * 100.0) / total_ticks;
}
+/*
+ * smbstat_wrk_init
+ */
static void
-smbstat_init(void)
+smbstat_wrk_init(void)
{
- char smbsrv_name[KSTAT_STRLEN];
+ smbstat_wrk_ksp =
+ kstat_lookup(smbstat_ksc, "unix", -1, SMBSRV_KSTAT_WORKERS);
+ if (smbstat_wrk_ksp == NULL)
+ smbstat_fail(1,
+ gettext("cannot retrieve smbsrv workers kstat\n"));
+}
- (void) snprintf(smbsrv_name, sizeof (smbsrv_name), "%s%d",
- SMBSRV_KSTAT_NAME, getzoneid());
+static void
+smbstat_wrk_fini(void)
+{
+ smbstat_wrk_ksp = NULL;
+}
- if ((kc = kstat_open()) == NULL)
- smbstat_fail(1, gettext("kstat_open(): can't open /dev/kstat"));
+/*
+ * smbstat_wrk_snapshot
+ */
+static void
+smbstat_wrk_snapshot(void)
+{
+ smbstat_wrk_snapshot_t *curr;
+ kstat_named_t *kn;
- smb_server = kstat_lookup(kc, SMBSRV_KSTAT_MODULE, 0, smbsrv_name);
- smb_cmds = kstat_lookup(kc, SMBSRV_KSTAT_MODULE, 0,
- SMBSRV_KSTAT_NAME_CMDS);
+ curr = smbstat_wrk_current_snapshot();
- if ((smb_server == NULL) || (smb_cmds == NULL))
- smbstat_fail(0, gettext("kstat lookups failed for smb. "
- "Your kernel module may not be loaded\n"));
+ if (kstat_read(smbstat_ksc, smbstat_wrk_ksp, NULL) == -1)
+ smbstat_fail(1, gettext("kstat_read('%s') failed"),
+ smbstat_wrk_ksp->ks_name);
+
+ kn = kstat_data_lookup(smbstat_wrk_ksp, "maxthreads");
+ if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64))
+ smbstat_fail(1, gettext("kstat_read('%s') failed"),
+ "maxthreads");
+ curr->ws_maxthreads = kn->value.ui64;
+
+ kn = kstat_data_lookup(smbstat_wrk_ksp, "bnalloc");
+ if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64))
+ smbstat_fail(1, gettext("kstat_read('%s') failed"),
+ "bnalloc");
+ curr->ws_bnalloc = kn->value.ui64;
}
+/*
+ * smbstat_wrk_process
+ */
static void
-smbstat_fini(void)
+smbstat_wrk_process(void)
{
- (void) kstat_close(kc);
+ smbstat_wrk_snapshot_t *curr;
+
+ curr = smbstat_wrk_current_snapshot();
+
+ if (curr->ws_maxthreads >= curr->ws_bnalloc)
+ smbstat_srv_info.si_sat = B_TRUE;
+ else
+ smbstat_srv_info.si_sat = B_FALSE;
}
-static int
-smbstat_width(kstat_t *req, int field_width)
-{
- int i, nreq, len;
- char fixlen[128];
- kstat_named_t *knp;
-
- knp = KSTAT_NAMED_PTR(req);
- nreq = req->ks_ndata;
-
- for (i = 0; i < nreq; i++) {
- len = strlen(knp[i].name) + 1;
- if (field_width < len)
- field_width = len;
- (void) sprintf(fixlen, "%" PRIu64, knp[i].value.ui64);
- len = strlen(fixlen) + 1;
- if (field_width < len)
- field_width = len;
+/*
+ * smbstat_wrk_current_snapshot
+ */
+static smbstat_wrk_snapshot_t *
+smbstat_wrk_current_snapshot(void)
+{
+ return (&smbstat_wrk_snapshots[smbstat_snapshot_idx]);
+}
+
+/*
+ * smbstat_srv_init
+ */
+static void
+smbstat_srv_init(void)
+{
+ smbstat_srv_ksp = kstat_lookup(smbstat_ksc, SMBSRV_KSTAT_MODULE,
+ getzoneid(), SMBSRV_KSTAT_STATISTICS);
+ if (smbstat_srv_ksp == NULL)
+ smbstat_fail(1, gettext("cannot retrieve smbsrv kstat\n"));
+}
+
+/*
+ * smbstat_srv_fini
+ */
+static void
+smbstat_srv_fini(void)
+{
+ smbstat_srv_ksp = NULL;
+}
+
+/*
+ * smbstat_srv_snapshot
+ *
+ * Take a snapshot of the smbsrv module statistics.
+ */
+static void
+smbstat_srv_snapshot(void)
+{
+ smbstat_srv_snapshot_t *curr;
+
+ curr = smbstat_srv_current_snapshot();
+
+ if ((kstat_read(smbstat_ksc, smbstat_srv_ksp, NULL) == -1) ||
+ (smbstat_srv_ksp->ks_data_size != sizeof (curr->ss_data)))
+ smbstat_fail(1, gettext("kstat_read('%s') failed"),
+ smbstat_srv_ksp->ks_name);
+
+ curr->ss_snaptime = smbstat_srv_ksp->ks_snaptime;
+ bcopy(smbstat_srv_ksp->ks_data, &curr->ss_data, sizeof (curr->ss_data));
+}
+
+/*
+ * smbstat_srv_process
+ *
+ * Processes the snapshot data.
+ */
+static void
+smbstat_srv_process(void)
+{
+ smbstat_srv_snapshot_t *curr, *prev;
+
+ curr = smbstat_srv_current_snapshot();
+ prev = smbstat_srv_previous_snapshot();
+
+ if (prev->ss_snaptime == 0)
+ smbstat_srv_info.si_hretime =
+ smbstat_hrtime_delta(curr->ss_data.ks_start_time,
+ curr->ss_snaptime);
+ else
+ smbstat_srv_info.si_hretime =
+ smbstat_hrtime_delta(prev->ss_snaptime, curr->ss_snaptime);
+
+ smbstat_srv_info.si_etime = smbstat_srv_info.si_hretime / NANOSEC;
+ smbstat_srv_info.si_total_nreqs =
+ smbstat_sub_64(curr->ss_data.ks_nreq, prev->ss_data.ks_nreq);
+
+ if (smbstat_opt_c)
+ smbstat_srv_process_counters(curr);
+ if (smbstat_opt_t)
+ smbstat_srv_process_throughput(curr, prev);
+ if (smbstat_opt_u)
+ smbstat_srv_process_utilization(curr, prev);
+ if (smbstat_opt_r)
+ smbstat_srv_process_requests(curr, prev);
+}
+
+/*
+ * smbstat_srv_process_counters
+ */
+static void
+smbstat_srv_process_counters(smbstat_srv_snapshot_t *curr)
+{
+ smbstat_srv_info.si_nbt_sess = curr->ss_data.ks_nbt_sess;
+ smbstat_srv_info.si_tcp_sess = curr->ss_data.ks_tcp_sess;
+ smbstat_srv_info.si_users = curr->ss_data.ks_users;
+ smbstat_srv_info.si_trees = curr->ss_data.ks_trees;
+ smbstat_srv_info.si_files = curr->ss_data.ks_files;
+ smbstat_srv_info.si_pipes = curr->ss_data.ks_pipes;
+}
+
+/*
+ * smbstat_srv_process_throughput
+ *
+ * Processes the data relative to the throughput of the smbsrv module and
+ * stores the results in the structure smbstat_srv_info.
+ */
+static void
+smbstat_srv_process_throughput(
+ smbstat_srv_snapshot_t *curr,
+ smbstat_srv_snapshot_t *prev)
+{
+ smbstat_srv_info.si_tbs =
+ smbstat_sub_64(curr->ss_data.ks_txb, prev->ss_data.ks_txb);
+ smbstat_srv_info.si_tbs /= smbstat_srv_info.si_etime;
+ smbstat_srv_info.si_rbs =
+ smbstat_sub_64(curr->ss_data.ks_rxb, prev->ss_data.ks_rxb);
+ smbstat_srv_info.si_rbs /= smbstat_srv_info.si_etime;
+ smbstat_srv_info.si_rqs = smbstat_srv_info.si_total_nreqs;
+ smbstat_srv_info.si_rqs /= smbstat_srv_info.si_etime;
+
+ smbstat_srv_info.si_rds = smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_READ].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_READ].kr_nreq);
+ smbstat_srv_info.si_rds += smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_LOCK_AND_READ].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_LOCK_AND_READ].kr_nreq);
+ smbstat_srv_info.si_rds += smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_READ_RAW].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_READ_RAW].kr_nreq);
+ smbstat_srv_info.si_rds += smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_READ_ANDX].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_READ_ANDX].kr_nreq);
+ smbstat_srv_info.si_rds /= smbstat_srv_info.si_etime;
+
+ smbstat_srv_info.si_wrs = smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_WRITE].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_WRITE].kr_nreq);
+ smbstat_srv_info.si_wrs += smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_WRITE_AND_UNLOCK].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_WRITE_AND_UNLOCK].kr_nreq);
+ smbstat_srv_info.si_wrs += smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_WRITE_RAW].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_WRITE_RAW].kr_nreq);
+ smbstat_srv_info.si_wrs += smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_WRITE_AND_CLOSE].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_WRITE_AND_CLOSE].kr_nreq);
+ smbstat_srv_info.si_wrs += smbstat_sub_64(
+ curr->ss_data.ks_reqs[SMB_COM_WRITE_ANDX].kr_nreq,
+ prev->ss_data.ks_reqs[SMB_COM_WRITE_ANDX].kr_nreq);
+ smbstat_srv_info.si_wrs /= smbstat_srv_info.si_etime;
+}
+
+/*
+ * smbstat_srv_process_utilization
+ *
+ * Processes the data relative to the utilization of the smbsrv module and
+ * stores the results in the structure smbstat_srv_info.
+ */
+static void
+smbstat_srv_process_utilization(
+ smbstat_srv_snapshot_t *curr,
+ smbstat_srv_snapshot_t *prev)
+{
+ double tw_delta, tr_delta;
+ double w_delta, r_delta;
+ double tps, rqs;
+
+ w_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wlentime,
+ curr->ss_data.ks_utilization.ku_wlentime);
+ r_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rlentime,
+ curr->ss_data.ks_utilization.ku_rlentime);
+ tw_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wtime,
+ curr->ss_data.ks_utilization.ku_wtime);
+ tr_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rtime,
+ curr->ss_data.ks_utilization.ku_rtime);
+ rqs = smbstat_srv_info.si_total_nreqs / smbstat_srv_info.si_etime;
+
+ /* Average number of requests waiting */
+ if (w_delta != 0)
+ smbstat_srv_info.si_avw = w_delta / smbstat_srv_info.si_hretime;
+ else
+ smbstat_srv_info.si_avw = 0.0;
+
+ /* Average number of request running */
+ if (r_delta != 0)
+ smbstat_srv_info.si_avr = r_delta / smbstat_srv_info.si_hretime;
+ else
+ smbstat_srv_info.si_avr = 0.0;
+
+ /* Utilization */
+ smbstat_srv_info.si_upct =
+ (smbstat_srv_info.si_avr / curr->ss_data.ks_maxreqs) * 100;
+
+ /* Average wait service time in milliseconds */
+ smbstat_srv_info.si_rserv = 0.0;
+ smbstat_srv_info.si_wserv = 0.0;
+ if (rqs > 0.0 &&
+ (smbstat_srv_info.si_avw != 0.0 ||
+ smbstat_srv_info.si_avr != 0.0)) {
+ tps = 1 / rqs;
+ if (smbstat_srv_info.si_avw != 0.0)
+ smbstat_srv_info.si_wserv =
+ smbstat_srv_info.si_avw * tps;
+ if (smbstat_srv_info.si_avr != 0.0)
+ smbstat_srv_info.si_rserv =
+ smbstat_srv_info.si_avr * tps;
+ }
+
+ /* % of time there is a transaction waiting for service */
+ if (tw_delta != 0) {
+ smbstat_srv_info.si_wpct = tw_delta;
+ smbstat_srv_info.si_wpct /= smbstat_srv_info.si_hretime;
+ smbstat_srv_info.si_wpct *= 100.0;
+ } else {
+ smbstat_srv_info.si_wpct = 0.0;
+ }
+
+ /* % of time there is a transaction running */
+ if (tr_delta != 0) {
+ smbstat_srv_info.si_rpct = tr_delta;
+ smbstat_srv_info.si_rpct /= smbstat_srv_info.si_hretime;
+ smbstat_srv_info.si_rpct *= 100.0;
+ } else {
+ smbstat_srv_info.si_rpct = 0.0;
}
- return (field_width);
}
+/*
+ * smbstat_srv_process_requests
+ *
+ * Processes the data relative to the SMB requests and stores the results in
+ * the structure smbstat_srv_info.
+ */
static void
-smbstat_print(const char *title_string, kstat_t *req, int field_width)
+smbstat_srv_process_requests(
+ smbstat_srv_snapshot_t *curr,
+ smbstat_srv_snapshot_t *prev)
{
- int i, j, nreq, ncolumns;
- char fixlen[128];
- kstat_named_t *knp;
+ smbstat_req_info_t *info;
+ double nrqs;
+ int i, idx;
- if (req == NULL)
- return;
+ info = smbstat_srv_info.si_reqs;
- if (field_width == 0)
- return;
+ for (i = 0; i < SMB_COM_NUM; i++) {
+ idx = info[i].ri_opcode;
+
+ nrqs = smbstat_sub_64(curr->ss_data.ks_reqs[idx].kr_nreq,
+ prev->ss_data.ks_reqs[idx].kr_nreq);
+
+ info[i].ri_rqs = nrqs / smbstat_srv_info.si_etime;
- (void) printf("%s\n", title_string);
- ncolumns = (MAX_COLUMNS -1)/field_width;
+ info[i].ri_rbs = smbstat_sub_64(
+ curr->ss_data.ks_reqs[idx].kr_rxb,
+ prev->ss_data.ks_reqs[idx].kr_rxb) /
+ smbstat_srv_info.si_etime;
- knp = KSTAT_NAMED_PTR(req);
- nreq = req->ks_ndata;
+ info[i].ri_tbs = smbstat_sub_64(
+ curr->ss_data.ks_reqs[idx].kr_txb,
+ prev->ss_data.ks_reqs[idx].kr_txb) /
+ smbstat_srv_info.si_etime;
- for (i = 0; i < nreq; i += ncolumns) {
- /* prints out the titles of the columns */
- for (j = i; j < MIN(i + ncolumns, nreq); j++) {
- (void) printf("%-*s", field_width, knp[j].name);
+ info[i].ri_pct = nrqs * 100;
+ if (smbstat_srv_info.si_total_nreqs > 0)
+ info[i].ri_pct /= smbstat_srv_info.si_total_nreqs;
+
+ if (prev->ss_snaptime == 0) {
+ /* First time. Take the aggregate */
+ info[i].ri_stddev =
+ curr->ss_data.ks_reqs[idx].kr_a_stddev;
+ info[i].ri_mean = curr->ss_data.ks_reqs[idx].kr_a_mean;
+ } else {
+ /* Take the differential */
+ info[i].ri_stddev =
+ curr->ss_data.ks_reqs[idx].kr_d_stddev;
+ info[i].ri_mean = curr->ss_data.ks_reqs[idx].kr_d_mean;
}
- (void) printf("\n");
- /* prints out the stat numbers */
- for (j = i; j < MIN(i + ncolumns, nreq); j++) {
- (void) sprintf(fixlen, "%" PRIu64 " ",
- knp[j].value.ui64);
- (void) printf("%-*s", field_width, fixlen);
+ if (nrqs > 0) {
+ info[i].ri_stddev /= nrqs;
+ info[i].ri_stddev = sqrt(info[i].ri_stddev);
+ } else {
+ info[i].ri_stddev = 0;
}
- (void) printf("\n");
-
+ info[i].ri_stddev /= NANOSEC;
+ info[i].ri_mean /= NANOSEC;
}
}
+/*
+ * smbstat_srv_current_snapshot
+ *
+ * Returns the current snapshot.
+ */
+static smbstat_srv_snapshot_t *
+smbstat_srv_current_snapshot(void)
+{
+ return (&smbstat_srv_snapshots[smbstat_snapshot_idx]);
+}
+
+/*
+ * smbstat_srv_previous_snapshot
+ *
+ * Returns the previous snapshot.
+ */
+static smbstat_srv_snapshot_t *
+smbstat_srv_previous_snapshot(void)
+{
+ int idx;
+
+ idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK;
+ return (&smbstat_srv_snapshots[idx]);
+}
+
+/*
+ * smbstat_usage
+ *
+ * Prints out a help message.
+ */
static void
-smbstat_usage(void)
+smbstat_usage(FILE *fd, int exit_code)
{
- (void) fprintf(stderr, gettext("Usage: smbstat [-id]\n"));
- exit(1);
+ (void) fprintf(fd, gettext(SMBSTAT_HELP));
+ exit(exit_code);
}
+/*
+ * smbstat_fail
+ *
+ * Prints out to stderr an error message and exits the process.
+ */
static void
smbstat_fail(int do_perror, char *message, ...)
{
@@ -282,30 +1112,196 @@ smbstat_fail(int do_perror, char *message, ...)
exit(1);
}
-static kid_t
-smbstat_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data)
+/*
+ * smbstat_sub_64
+ *
+ * Substract 2 uint64_t and returns a double.
+ */
+static double
+smbstat_sub_64(uint64_t a, uint64_t b)
{
- kid_t kstat_chain_id = kstat_read(kc, ksp, data);
+ return ((double)(a - b));
+}
- if (kstat_chain_id == -1)
- smbstat_fail(1, gettext("kstat_read('%s') failed"),
- ksp->ks_name);
- return (kstat_chain_id);
+/*
+ * smbstat_zero
+ *
+ * Returns zero if the value passed in is less than 1.
+ */
+static double
+smbstat_zero(double value)
+{
+ if (value < 1)
+ value = 0;
+ return (value);
+}
+
+/*
+ * smbstat_strtoi
+ *
+ * Converts a string representing an integer value into its binary value.
+ * If the conversion fails this routine exits the process.
+ */
+static uint_t
+smbstat_strtoi(char const *val, char *errmsg)
+{
+ char *end;
+ long tmp;
+
+ errno = 0;
+ tmp = strtol(val, &end, 10);
+ if (*end != '\0' || errno)
+ smbstat_fail(1, "%s %s", errmsg, val);
+ return ((uint_t)tmp);
+}
+
+/*
+ * smbstat_termio_init
+ *
+ * Determines the size of the terminal associated with the process.
+ */
+static void
+smbstat_termio_init(void)
+{
+ char *envp;
+
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &smbstat_ws) != -1) {
+ if (smbstat_ws.ws_row == 0) {
+ envp = getenv("LINES");
+ if (envp != NULL)
+ smbstat_ws.ws_row = atoi(envp);
+ }
+
+ if (smbstat_ws.ws_col == 0) {
+ envp = getenv("COLUMNS");
+ if (envp != NULL)
+ smbstat_ws.ws_row = atoi(envp);
+ }
+ }
+ if (smbstat_ws.ws_col == 0)
+ smbstat_ws.ws_col = 80;
+ if (smbstat_ws.ws_row == 0)
+ smbstat_ws.ws_row = 25;
+}
+
+/*
+ * smbstat_snapshot_idx_inc
+ *
+ * Increments the snapshot index.
+ */
+static void
+smbstat_snapshot_inc_idx(void)
+{
+ smbstat_snapshot_idx++;
+ smbstat_snapshot_idx &= SMBSTAT_SNAPSHOT_MASK;
}
/*
- * Enable libumem debugging by default on DEBUG builds.
+ * smbstat_req_cmp_name
+ *
+ * Call back function passed to qsort() when the list of requests must be sorted
+ * by name.
*/
-#ifdef DEBUG
-const char *
-_umem_debug_init(void)
+static int
+smbstat_req_cmp_name(const void *obj1, const void *obj2)
{
- return ("default,verbose"); /* $UMEM_DEBUG setting */
+ return (strncasecmp(
+ ((smbstat_req_info_t *)obj1)->ri_name,
+ ((smbstat_req_info_t *)obj2)->ri_name,
+ sizeof (((smbstat_req_info_t *)obj2)->ri_name)));
}
-const char *
-_umem_logging_init(void)
+/*
+ * smbstat_req_order
+ *
+ * Snapshots the smbsrv module statistics once to get the name of the requests.
+ * The request list is smbstat_srv_info is then sorted by name or by code
+ * depending on the boolean smbstat_opt_a.
+ * The function should be called once during initialization.
+ */
+static void
+smbstat_req_order(void)
+{
+ smbstat_req_info_t *info;
+ smb_kstat_req_t *reqs;
+ int i;
+
+ smbstat_srv_snapshot();
+ reqs = smbstat_srv_current_snapshot()->ss_data.ks_reqs;
+ info = smbstat_srv_info.si_reqs;
+
+ for (i = 0; i < SMB_COM_NUM; i++) {
+ (void) strlcpy(info[i].ri_name, reqs[i].kr_name,
+ sizeof (reqs[i].kr_name));
+ info[i].ri_opcode = i;
+ }
+ if (smbstat_opt_n)
+ qsort(info, SMB_COM_NUM, sizeof (smbstat_req_info_t),
+ smbstat_req_cmp_name);
+}
+
+/*
+ * Return the number of ticks delta between two hrtime_t
+ * values. Attempt to cater for various kinds of overflow
+ * in hrtime_t - no matter how improbable.
+ */
+static double
+smbstat_hrtime_delta(hrtime_t old, hrtime_t new)
+{
+ uint64_t del;
+
+ if ((new >= old) && (old >= 0L))
+ return ((double)(new - old));
+ /*
+ * We've overflowed the positive portion of an hrtime_t.
+ */
+ if (new < 0L) {
+ /*
+ * The new value is negative. Handle the case where the old
+ * value is positive or negative.
+ */
+ uint64_t n1;
+ uint64_t o1;
+
+ n1 = -new;
+ if (old > 0L)
+ return ((double)(n1 - old));
+
+ o1 = -old;
+ del = n1 - o1;
+ return ((double)del);
+ }
+
+ /*
+ * Either we've just gone from being negative to positive *or* the last
+ * entry was positive and the new entry is also positive but *less* than
+ * the old entry. This implies we waited quite a few days on a very fast
+ * system between displays.
+ */
+ if (old < 0L) {
+ uint64_t o2;
+ o2 = -old;
+ del = UINT64_MAX - o2;
+ } else {
+ del = UINT64_MAX - old;
+ }
+ del += new;
+ return ((double)del);
+}
+
+static void *
+smbstat_zalloc(size_t size)
+{
+ void *ptr;
+
+ ptr = umem_zalloc(size, UMEM_DEFAULT);
+ if (ptr == NULL)
+ smbstat_fail(1, gettext("out of memory"));
+ return (ptr);
+}
+
+static void
+smbstat_free(void *ptr, size_t size)
{
- return ("fail,contents"); /* $UMEM_LOGGING setting */
+ umem_free(ptr, size);
}
-#endif